<?xml version='1.0' encoding='utf-8'?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://https:///</id>
  <title><![CDATA[saikumarmk.com]]></title>
  <icon>/assets/fatpika.png</icon>
  <link href="https://https://" />
  <link href="https://https:///atom.xml" rel="self" type="application/atom+xml" />
  <updated>2026-07-05T15:57:58.367Z</updated>
  <author>
    <name><![CDATA[Sai]]></name>
  </author>
  <category term="blog" scheme="https://https:///?tags=blog" />
  <category term="reverse-engineering" scheme="https://https:///?tags=reverse-engineering" />
  <category term="yakuza" scheme="https://https:///?tags=yakuza" />
  <category term="blog-post" scheme="https://https:///?tags=blog-post" />
  <category term="recursion" scheme="https://https:///?tags=recursion" />
  <category term="dynamic-programming" scheme="https://https:///?tags=dynamic-programming" />
  <category term="linked-lists" scheme="https://https:///?tags=linked-lists" />
  <category term="trees" scheme="https://https:///?tags=trees" />
  <category term="leetcode" scheme="https://https:///?tags=leetcode" />
  <category term="yggdrasil" scheme="https://https:///?tags=yggdrasil" />
  <category term="Lagrangian" scheme="https://https:///?tags=Lagrangian" />
  <category term="Hamiltonian" scheme="https://https:///?tags=Hamiltonian" />
  <category term="dynamics" scheme="https://https:///?tags=dynamics" />
  <category term="physics" scheme="https://https:///?tags=physics" />
  <category term="systems-hpc" scheme="https://https:///?tags=systems-hpc" />
  <category term="distributed" scheme="https://https:///?tags=distributed" />
  <category term="DP" scheme="https://https:///?tags=DP" />
  <category term="FSDP" scheme="https://https:///?tags=FSDP" />
  <category term="ZeRO" scheme="https://https:///?tags=ZeRO" />
  <category term="sharding" scheme="https://https:///?tags=sharding" />
  <category term="mental-models" scheme="https://https:///?tags=mental-models" />
  <category term="gen-media" scheme="https://https:///?tags=gen-media" />
  <category term="ODE" scheme="https://https:///?tags=ODE" />
  <category term="flow-matching" scheme="https://https:///?tags=flow-matching" />
  <category term="trajectory" scheme="https://https:///?tags=trajectory" />
  <category term="diffusion" scheme="https://https:///?tags=diffusion" />
  <category term="continuous-normalizing-flows" scheme="https://https:///?tags=continuous-normalizing-flows" />
  <category term="swe" scheme="https://https:///?tags=swe" />
  <category term="fp" scheme="https://https:///?tags=fp" />
  <category term="rl" scheme="https://https:///?tags=rl" />
  <category term="online" scheme="https://https:///?tags=online" />
  <category term="distribution-shift" scheme="https://https:///?tags=distribution-shift" />
  <category term="stability" scheme="https://https:///?tags=stability" />
  <category term="iterative-training" scheme="https://https:///?tags=iterative-training" />
  <category term="RL" scheme="https://https:///?tags=RL" />
  <category term="REINFORCE" scheme="https://https:///?tags=REINFORCE" />
  <category term="actor-critic" scheme="https://https:///?tags=actor-critic" />
  <category term="policy-gradient" scheme="https://https:///?tags=policy-gradient" />
  <category term="PPO" scheme="https://https:///?tags=PPO" />
  <category term="implementation" scheme="https://https:///?tags=implementation" />
  <category term="evaluation" scheme="https://https:///?tags=evaluation" />
  <category term="GRPO" scheme="https://https:///?tags=GRPO" />
  <category term="5D-parallelism" scheme="https://https:///?tags=5D-parallelism" />
  <category term="overlap" scheme="https://https:///?tags=overlap" />
  <category term="bucketing" scheme="https://https:///?tags=bucketing" />
  <category term="playbook" scheme="https://https:///?tags=playbook" />
  <category term="ultra-scale" scheme="https://https:///?tags=ultra-scale" />
  <category term="software" scheme="https://https:///?tags=software" />
  <category term="random" scheme="https://https:///?tags=random" />
  <category term="web-dev" scheme="https://https:///?tags=web-dev" />
  <category term="slides" scheme="https://https:///?tags=slides" />
  <category term="meta" scheme="https://https:///?tags=meta" />
  <category term="pokemon" scheme="https://https:///?tags=pokemon" />
  <category term="simulation" scheme="https://https:///?tags=simulation" />
  <category term="university" scheme="https://https:///?tags=university" />
  <category term="graph" scheme="https://https:///?tags=graph" />
  <category term="technical" scheme="https://https:///?tags=technical" />
  <category term="career" scheme="https://https:///?tags=career" />
  <category term="update" scheme="https://https:///?tags=update" />
  <category term="scraping" scheme="https://https:///?tags=scraping" />
  <category term="visualisation" scheme="https://https:///?tags=visualisation" />
  <category term="C" scheme="https://https:///?tags=C" />
  <category term="Python" scheme="https://https:///?tags=Python" />
  <category term="SBC" scheme="https://https:///?tags=SBC" />
  <category term="Dash" scheme="https://https:///?tags=Dash" />
  <category term="Data visualisation" scheme="https://https:///?tags=Data%20visualisation" />
  <category term="webassembly" scheme="https://https:///?tags=webassembly" />
  <category term="emulation" scheme="https://https:///?tags=emulation" />
  <category term="tutorial" scheme="https://https:///?tags=tutorial" />
  <category term="data-science" scheme="https://https:///?tags=data-science" />
  <category term="visualization" scheme="https://https:///?tags=visualization" />
  <category term="python" scheme="https://https:///?tags=python" />
  <category term="summary" scheme="https://https:///?tags=summary" />
  <category term="uwucode" scheme="https://https:///?tags=uwucode" />
  <entry>
    <title type="html"><![CDATA[Sai's GPU Brrr Reading List]]></title>
    <link href="https://https:///reading-list-gpu-brr" />
    <id>https://https:///reading-list-gpu-brr</id>
    <published>2026-06-21T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <summary type="html"><![CDATA[A GPU-performance reading map for making deep learning faster: hardware hierarchy, rooflines, kernels, profiling, distributed training, serving, quantization, and monokernels.]]></summary>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h1 id="gpu-brrr-reading-list"><a href="#gpu-brrr-reading-list">GPU Brrr Reading List</a></h1> <p>I’ve found myself reading articles, blogs, papers and lecture notes across <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><mtext>ML</mtext><mo separator="true">,</mo><mtext>SWE</mtext><mo separator="true">,</mo><mtext>Maths</mtext><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\{\text{ML}, \text{SWE}, \text{Maths}\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">{</span><span class="mord text"><span class="mord">ML</span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord text"><span class="mord">SWE</span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord text"><span class="mord">Maths</span></span><span class="mclose">}</span></span></span></span><!----></span> as a form of passive learning, then turning the useful bits into implementation later.</p> <p>This page is just the GPU/performance side of that habit. How do we make the GPU go brr? The answer?</p> <ol><li>Understand the expensive bit of hardward</li> <li>Measure and profile</li> <li>Attack wasted movement, launches and idle time, keep everything close together</li> <li>Fuse it back together.</li></ol> <h2 id="act-1-the-gpu-hierarchy"><a href="#act-1-the-gpu-hierarchy">Act 1: The GPU Hierarchy</a></h2> <p>Three hierarchies get taught together because they interact constantly: execution hierarchy, hardware hierarchy and memory hierarchy.</p> <ul><li>Execution: grid, blocks, warps, threads.</li> <li>Hardware: GPU, SMs, tensor cores / CUDA cores.</li> <li>Memory: registers, shared memory / SRAM, L2, HBM.</li></ul> <p>Small mental note: each block runs on an SM (Streaming Multiprocessor, think like a CPU); the GPU chip is the grid. Within the hierarchy, registers are closest/fastest, then shared memory, then global memory/HBM.</p> <p>Core idea: <strong>compute is cheap; moving data is expensive.</strong> Most of the resources below are different ways of moving fewer bytes, moving smaller bytes, reusing bytes more often, or keeping the GPU busy while bytes are moving.</p> <h3 id="resources"><a href="#resources">Resources</a></h3> <ul><li><a href="https://mlc.ai/modern-gpu-programming-for-mlsys/chapter_background/index.html" rel="nofollow noopener noreferrer external" target="_blank">GPU Execution Model - Modern GPU Programming For MLSys</a> - concise overview of the GPU execution model.</li> <li><a href="https://mlc.ai/modern-gpu-programming-for-mlsys/" rel="nofollow noopener noreferrer external" target="_blank">Modern GPU Programming for ML Systems</a> - full course/book-style path for GPU programming in ML systems.</li> <li><a href="https://www.youtube.com/watch?v=xewKxorikwE" rel="nofollow noopener noreferrer external" target="_blank">Give Me 30 min, I’ll Make CUDA Click Forever</a> - CUDA mental model video.</li> <li><a href="https://github.com/cuda-mode/lectures" rel="nofollow noopener noreferrer external" target="_blank">CUDA MODE lectures</a> - CUDA/GPU programming lectures.</li> <li><a href="https://github.com/anmolgupt/cuda_mode_lectures/tree/main/lecture_001" rel="nofollow noopener noreferrer external" target="_blank">CUDA MODE lecture 001 materials</a> - lecture materials from the replay dump.</li> <li><a href="https://www.youtube.com/watch?v=V1tINV2-9p4" rel="nofollow noopener noreferrer external" target="_blank">Stanford CS149 Lecture 1: Why Parallelism? Why Efficiency?</a> - parallel-computing context.</li></ul> <h2 id="act-15-the-gpu-is-a-moving-target"><a href="#act-15-the-gpu-is-a-moving-target">Act 1.5: The GPU Is a Moving Target</a></h2> <p>There is not one GPU. Each generation moves the numbers: HBM bandwidth and capacity, tensor-core throughput, supported precision formats and async data-movement machinery.</p> <p>That matters because the best optimization depends on the hardware. Ampere, Hopper and Blackwell do not have the same precision formats, memory hierarchy details, or kernel sweet spots.</p> <h3 id="resources-1"><a href="#resources-1">Resources</a></h3> <ul><li><a href="https://mlc.ai/modern-gpu-programming-for-mlsys/" rel="nofollow noopener noreferrer external" target="_blank">Modern GPU Programming for ML Systems</a> - useful for the generation-by-generation hardware context.</li> <li><a href="https://pytorch.org/blog/some-matrix-multiplication-engines-are-not-as-accurate-as-we-thought/" rel="nofollow noopener noreferrer external" target="_blank">Some matrix multiplication engines are not as accurate as we thought</a> - hardware/runtime numerics are part of performance engineering.</li> <li><a href="https://www.booktopia.com.au/ai-systems-performance-engineering-chris-fregly/book/9798341627789.html" rel="nofollow noopener noreferrer external" target="_blank">AI Systems Performance Engineering</a> - book reference for AI performance engineering.</li></ul> <h2 id="act-2-performance-models-and-rooflines"><a href="#act-2-performance-models-and-rooflines">Act 2: Performance Models and Rooflines</a></h2> <p>Before touching a kernel, identify which resource is limiting it:</p> <ul><li>Compute: math units are saturated.</li> <li>Memory: math units are waiting for bytes.</li> <li>Overhead: launches/setup/synchronization dominate.</li></ul> <p>The roofline model is the main picture: low arithmetic intensity lives on the memory-bandwidth diagonal; high arithmetic intensity hits the compute ceiling. A lot of deep learning optimization is pushing work up and right by increasing reuse or avoiding materialization.</p> <h3 id="resources-2"><a href="#resources-2">Resources</a></h3> <ul><li><a href="https://horace.io/brrr_intro.html" rel="nofollow noopener noreferrer external" target="_blank">Making Deep Learning Go Brrrr From First Principles</a> - roofline model, arithmetic intensity, and the base mental model for “why isn’t this faster?”</li> <li><a href="https://jax-ml.github.io/scaling-book/" rel="nofollow noopener noreferrer external" target="_blank">How To Scale Your Model</a> - the JAX scaling book; systems view of LLMs, rooflines, parallelism and large-scale training economics.</li> <li><a href="https://kipp.ly/transformer-inference-arithmetic/" rel="nofollow noopener noreferrer external" target="_blank">Transformer Inference Arithmetic</a> - forward-pass and KV-cache arithmetic for inference.</li> <li><a href="https://mlsysbook.ai/" rel="nofollow noopener noreferrer external" target="_blank">Machine Learning Systems</a> - broad ML systems book/reference.</li> <li><a href="https://www.sei.cmu.edu/blog/a-hitchhikers-guide-to-ml-training-infrastructure/" rel="nofollow noopener noreferrer external" target="_blank">A Hitchhiker’s Guide to ML Training Infrastructure</a> - broad overview of training infrastructure and hardware acceleration.</li></ul> <h2 id="act-3-profiling-torchcompile-and-fusion"><a href="#act-3-profiling-torchcompile-and-fusion">Act 3: Profiling, <code>torch.compile</code> and Fusion</a></h2> <p>The first optimization baseline is measurement. After that, the first automatic optimization is often compilation/fusion: capture the graph, remove Python overhead, fuse operations, and avoid HBM round-trips for intermediates.</p> <p>The catch: graph capture is shape-sensitive. Variable sequence length, video resolution, frame count and batch shape can turn “free speedup” into repeated recompilation unless shapes are bucketed or handled deliberately.</p> <h3 id="resources-3"><a href="#resources-3">Resources</a></h3> <ul><li><a href="https://huggingface.co/blog/torch-profiler" rel="nofollow noopener noreferrer external" target="_blank">Profiling in PyTorch, Part 1: A Beginner’s Guide to torch.profiler</a> - getting useful traces out of PyTorch.</li> <li><a href="https://huggingface.co/blog/torch-mlp-fusion" rel="nofollow noopener noreferrer external" target="_blank">Profiling in PyTorch, Part 2: From nn.Linear to a Fused MLP</a> - profiling through to fusion.</li> <li><a href="https://christianjmills.com/posts/cuda-mode-notes/lecture-001/#optimization-profiling-with-nsight-compute" rel="nofollow noopener noreferrer external" target="_blank">GPU MODE Lecture 1: How to profile CUDA kernels in PyTorch</a> - Nsight/PyTorch profiling notes.</li> <li><a href="https://x.com/ariG23498/status/2065025515241562322" rel="nofollow noopener noreferrer external" target="_blank">Aritra on X: Profiling deep learning layers</a> - thread on layer profiling.</li> <li><a href="https://www.youtube.com/watch?v=pHqcHzxx6I8" rel="nofollow noopener noreferrer external" target="_blank">Making GPUs Actually Fast: A Deep Dive into Training Performance</a> - Jane Street video on training performance.</li> <li><a href="https://github.com/JINO-ROHIT/ml-systems-notes/tree/main" rel="nofollow noopener noreferrer external" target="_blank">JINO-ROHIT/ml-systems-notes</a> - notes around Torch, distributed systems and ML systems.</li></ul> <h2 id="act-4-custom-kernels-and-flashattention"><a href="#act-4-custom-kernels-and-flashattention">Act 4: Custom Kernels and FlashAttention</a></h2> <p>Do not materialize large intermediates in HBM if they can be tiled, streamed, fused or consumed immediately. Do as much as you can in SRAM, or the shared memory.</p> <p>Matmul is the warmup example: naive global-memory reads, then coalescing, shared-memory tiling, register tiling, and eventually more hardware-specific tricks like async copies and warp specialization.</p> <p>FlashAttention is the attention version of the same idea: never build the full <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>N</mi><mo>×</mo><mi>N</mi></mrow><annotation encoding="application/x-tex">N \times N</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">N</span><span class="mspace"></span><span class="mbin">×</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">N</span></span></span></span><!----></span> score matrix in HBM. Tile the computation, keep the online softmax state, and stream blocks through fast memory.</p> <h3 id="kernel-resources"><a href="#kernel-resources">Kernel Resources</a></h3> <ul><li><a href="https://siboehm.com/articles/22/CUDA-MMM" rel="nofollow noopener noreferrer external" target="_blank">How to Optimize a CUDA Matmul Kernel for cuBLAS-like Performance</a> - Simon Boehm’s CUDA matmul worklog.</li> <li><a href="https://siboehm.com/articles/22/Fast-MMM-on-CPU" rel="nofollow noopener noreferrer external" target="_blank">Fast matrix multiplication on CPU</a> - useful contrast with GPU performance thinking.</li> <li><a href="https://triton-lang.org/main/getting-started/tutorials/01-vector-add.html" rel="nofollow noopener noreferrer external" target="_blank">Triton vector addition tutorial</a> - first small Triton kernel.</li> <li><a href="https://github.com/gpu-mode/Triton-Puzzles" rel="nofollow noopener noreferrer external" target="_blank">Triton Puzzles</a> - practice problems for Triton.</li> <li><a href="https://huggingface.co/blog/kernel-builder" rel="nofollow noopener noreferrer external" target="_blank">Hugging Face Kernel Builder</a> - practical workflow for custom kernels.</li> <li><a href="https://www.youtube.com/watch?v=Ok8vi6JemVQ" rel="nofollow noopener noreferrer external" target="_blank">Lecture 106: Hugging Face Kernels</a> - video on Hugging Face kernels.</li> <li><a href="https://gau-nernst.github.io/amd-a2a/" rel="nofollow noopener noreferrer external" target="_blank">My first Multi-GPU kernel: Writing All-to-all for AMD MI300X</a> - multi-GPU all-to-all kernel writeup.</li> <li><a href="https://x.com/waterloo_intern/status/2070643039668974060" rel="nofollow noopener noreferrer external" target="_blank">Making video go BRRRR</a> - video performance thread.</li></ul> <h3 id="flashattention-resources"><a href="#flashattention-resources">FlashAttention Resources</a></h3> <ul><li><a href="https://arxiv.org/abs/2205.14135" rel="nofollow noopener noreferrer external" target="_blank">FlashAttention paper</a> - attention as a memory-bound problem.</li> <li><a href="https://github.com/Dao-AILab/flash-attention/blob/main/flash_attn/flash_attn_triton.py" rel="nofollow noopener noreferrer external" target="_blank">FlashAttention Triton implementation</a> - source-level reference.</li> <li><a href="https://lubits.ch/flash/Part-1" rel="nofollow noopener noreferrer external" target="_blank">Flash Attention from Scratch Part 1</a> - implementation-oriented explanation.</li> <li><a href="https://github.com/lucidrains/flash-attention-jax" rel="nofollow noopener noreferrer external" target="_blank">flash-attention-jax</a> - JAX implementation.</li> <li><a href="https://github.com/lucidrains/flash-attention-jax/blob/main/flash_attention_jax/causal_flash_attention.py" rel="nofollow noopener noreferrer external" target="_blank">Causal FlashAttention in JAX</a> - specific causal attention file.</li></ul> <h2 id="act-5-multi-gpu-training-and-communication"><a href="#act-5-multi-gpu-training-and-communication">Act 5: Multi-GPU Training and Communication</a></h2> <p>Once one GPU is not enough, the memory hierarchy extends across devices. Moving data between GPUs is another expensive rung, so the same “move less / overlap more” principle returns.</p> <p>Core vocabulary:</p> <ul><li>Data parallelism: replicate model, split data, all-reduce gradients.</li> <li>Tensor parallelism: split layer math across devices.</li> <li>Pipeline parallelism: split depth into stages; watch for bubbles.</li> <li>FSDP / ZeRO: shard parameters, gradients and optimizer states.</li> <li>Collectives: all-reduce, all-gather, reduce-scatter.</li></ul> <h3 id="resources-4"><a href="#resources-4">Resources</a></h3> <ul><li><a href="https://cs336.stanford.edu/" rel="nofollow noopener noreferrer external" target="_blank">Stanford CS336: Language Modeling from Scratch</a> - broad spine for language-model systems.</li> <li><a href="https://cs336.stanford.edu/lectures/?trace=lecture_02" rel="nofollow noopener noreferrer external" target="_blank">CS336 lecture 2 trace</a> - PyTorch/einops trace from the course.</li> <li><a href="https://www.youtube.com/watch?v=kuYAsz7zspQ&amp;list=PLoROMvodv4rMqXOcazWaTUHhq-yembLCV&amp;index=6" rel="nofollow noopener noreferrer external" target="_blank">CS336 Lecture 2: PyTorch/einops</a> - video lecture.</li> <li><a href="https://huggingface.co/spaces/nanotron/ultrascale-playbook" rel="nofollow noopener noreferrer external" target="_blank">The Ultra-Scale Playbook</a> - Hugging Face/Nanotron guide to large-scale training.</li> <li><a href="https://huggingface.co/spaces/nanotron/ultrascale-playbook?section=gradient_accumulation" rel="nofollow noopener noreferrer external" target="_blank">Ultra-Scale Playbook: Gradient Accumulation</a> - specific section from the replay.</li> <li><a href="https://huggingface.co/spaces/nanotron/ultrascale-playbook?section=kernels" rel="nofollow noopener noreferrer external" target="_blank">Ultra-Scale Playbook: Kernels</a> - specific section from the replay.</li> <li><a href="https://huggingface.co/spaces/HuggingFaceTB/smol-training-playbook" rel="nofollow noopener noreferrer external" target="_blank">Smol Training Playbook</a> - practical training setup and parallelism choices.</li> <li><a href="https://arxiv.org/abs/2104.04473" rel="nofollow noopener noreferrer external" target="_blank">Megatron-LM pipeline parallelism</a> - pipeline bubbles and large-scale transformer training.</li> <li><a href="https://jino-rohit.github.io/blogs/11_collective_communication.html" rel="nofollow noopener noreferrer external" target="_blank">Jino Rohit’s collective communication notes</a> - communication primitives and distributed performance intuition.</li> <li><a href="https://ethansmith2000.substack.com/p/transport-muon-beating-muon-in-speed" rel="nofollow noopener noreferrer external" target="_blank">Transport Muon: Beating Muon in Speed and Performance in 1 Newton Step</a> - optimizer/performance reading.</li></ul> <h2 id="act-6-inference-and-serving"><a href="#act-6-inference-and-serving">Act 6: Inference and Serving</a></h2> <p>Serving has a different performance shape from training. You are juggling requests, the KV cache, prefill/decode split, batching and scheduling.</p> <ul><li>Prefill: lots of prompt tokens in parallel, often compute-heavy.</li> <li>Decode: one token at a time, repeatedly reading KV cache, often memory-bound.</li> <li>PagedAttention: treat KV cache like paged virtual memory to reduce fragmentation and increase concurrency.</li></ul> <h3 id="resources-5"><a href="#resources-5">Resources</a></h3> <ul><li><a href="https://siboehm.com/articles/22/llm-inference" rel="nofollow noopener noreferrer external" target="_blank">Fast LLM Inference From Scratch</a> - arithmetic and performance constraints for LLM inference.</li> <li><a href="https://arxiv.org/abs/2309.06180" rel="nofollow noopener noreferrer external" target="_blank">PagedAttention</a> - KV-cache paging as virtual memory.</li> <li><a href="https://moondream.ai/blog/popping-the-gpu-bubble" rel="nofollow noopener noreferrer external" target="_blank">Popping the GPU Bubble</a> - pipelined decoding and idle compute.</li> <li><a href="https://carteakey.dev/blog/local-inference/local-llm-optimization/" rel="nofollow noopener noreferrer external" target="_blank">Local LLM Inference Optimization: The Complete Guide</a> - practical local inference optimization guide.</li></ul> <h2 id="act-7-quantization-smaller-bytes-and-the-right-kernel"><a href="#act-7-quantization-smaller-bytes-and-the-right-kernel">Act 7: Quantization, Smaller Bytes and the Right Kernel</a></h2> <p>If a workload is memory-bound and you cannot move fewer values, move smaller values. Quantization reduces memory footprint and bandwidth demand, but it changes the accuracy and kernel-choice story.</p> <p>The right kernel depends on the workload. Dequant-then-compute kernels can be good for memory-bound decode; native low-precision GEMM can be better for compute-heavy prefill on new hardware.</p> <h3 id="resources-6"><a href="#resources-6">Resources</a></h3> <ul><li><a href="https://huggingface.co/collections/unsloth/gemma-4-qat" rel="nofollow noopener noreferrer external" target="_blank">Gemma 4 QAT - Unsloth collection</a> - quantization-aware training model collection.</li> <li><a href="https://unsloth.ai/docs/models/gemma-4/qat" rel="nofollow noopener noreferrer external" target="_blank">Gemma 4 QAT docs</a> - Unsloth documentation for QAT models.</li> <li><a href="https://huggingface.co/unsloth/gemma-4-26B-A4B-it-qat-GGUF/tree/main" rel="nofollow noopener noreferrer external" target="_blank">unsloth/gemma-4-26B-A4B-it-qat-GGUF</a> - GGUF model repo.</li> <li><a href="https://www.youtube.com/watch?v=O1AR4iL30mg" rel="nofollow noopener noreferrer external" target="_blank">The Magic of LLM Distillation</a> - distillation talk, useful background for compression.</li> <li><a href="https://timdettmers.com/" rel="nofollow noopener noreferrer external" target="_blank">Tim Dettmers</a> - quantization and efficient training/inference writing.</li></ul> <h2 id="act-8-monokernels-and-killing-boundaries"><a href="#act-8-monokernels-and-killing-boundaries">Act 8: monokernels and killing boundaries</a></h2> <p>if kernel boundaries, launch overhead and stragglers waste time, one extreme answer is to fuse much more aggressively. A monokernel/megakernel tries to keep the GPU busy by removing boundaries, loading ahead, and avoiding idle bubbles.</p> <h3 id="resources-7"><a href="#resources-7">Resources</a></h3> <ul><li><a href="https://hazyresearch.stanford.edu/blog/2025-05-27-no-bubbles" rel="nofollow noopener noreferrer external" target="_blank">Designing a Monokernel</a> - Hazy Research post on no-bubbles/monokernel design.</li></ul> <h2 id="compiler-and-runtime-side-quests"><a href="#compiler-and-runtime-side-quests">Compiler and Runtime Side Quests</a></h2> <p>Not everything is a Transformer. Tree inference and compiler/runtime work are also part of the performance map when the theme is “make model execution faster.”</p> <ul><li><a href="https://siboehm.com/articles/21/lleaves" rel="nofollow noopener noreferrer external" target="_blank">lleaves article</a> - compiled LightGBM inference.</li> <li><a href="https://siboehm.com/" rel="nofollow noopener noreferrer external" target="_blank">Simon Boehm’s blog</a> - CUDA, compiler and performance posts.</li></ul> <h2 id="people-and-feeds"><a href="#people-and-feeds">People and Feeds</a></h2> <p>People whose posts tend to feed this GPU/performance list.</p> <ul><li><a href="https://siboehm.com/" rel="nofollow noopener noreferrer external" target="_blank">Simon Boehm</a> - performance, inference and compiler-flavoured ML systems.</li> <li><a href="https://horace.io/" rel="nofollow noopener noreferrer external" target="_blank">Horace He</a> - performance models and PyTorch internals.</li> <li><a href="https://tridao.me/" rel="nofollow noopener noreferrer external" target="_blank">Tri Dao</a> - attention, sequence models and systems-aware algorithms.</li> <li><a href="https://timdettmers.com/" rel="nofollow noopener noreferrer external" target="_blank">Tim Dettmers</a> - quantization and efficient training/inference.</li> <li><a href="https://marksaroufim.substack.com/" rel="nofollow noopener noreferrer external" target="_blank">Mark Saroufim</a> - PyTorch, kernels and production ML systems.</li> <li><a href="https://x.com/jino_rohit" rel="nofollow noopener noreferrer external" target="_blank">Jino Rohit</a> - distributed systems, Torch and collective communication notes.</li> <li><a href="https://x.com/waterloo_intern" rel="nofollow noopener noreferrer external" target="_blank">Ali Taha</a> - model performance and video performance threads.</li> <li><a href="https://x.com/gaunernst" rel="nofollow noopener noreferrer external" target="_blank">Thien Tran</a> - GPU kernels and systems notes.</li> <li>Daniel Han Chen - Unsloth / model efficiency.</li></ul><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="blog" scheme="https://https:///?tags=blog" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Essence of Associativity, Halving and Logarithmic Structures]]></title>
    <link href="https://https:///essence-associativity" />
    <id>https://https:///essence-associativity</id>
    <published>2026-06-16T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.251Z</updated>
    <summary type="html"><![CDATA[Exploiting associativity on binary operators to speed up operations]]></summary>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h1 id="musings-on-sparse-tables-and-associativity"><a href="#musings-on-sparse-tables-and-associativity">Musings on Sparse Tables and Associativity</a></h1> <p>While learning about sparse tables, I found something quite insightful; the ideas behind binary lifting, where we we compute jump pointers to the nth ancestor, we break it up as the n/2th ancestor of the n/2th ancestor for a node. i.e <code>ancestor(node, n) = ancestor(ancestor(node, n/2), n/2)</code>. We can go further but more importantly, why does this structure look familiar?</p> <p>If we think back to binary exponentiation, we can write <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>a</mi><mi>n</mi></msup><mo>=</mo><mo stretchy="false">(</mo><msup><mi>a</mi><mrow><mi>n</mi><mi mathvariant="normal">/</mi><mn>2</mn></mrow></msup><mo stretchy="false">)</mo><mo>∗</mo><mo stretchy="false">(</mo><msup><mi>a</mi><mrow><mi>n</mi><mi mathvariant="normal">/</mi><mn>2</mn></mrow></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a^n = (a^{n/2}) * (a^{n/2})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mtight">/2</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mtight">/2</span></span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span> assuming <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span></span></span></span><!----></span> is even, and then in general:</p> <!----><pre class="shiki monokai" python="true"><div class="language-id">python</div><div class='code-container'><code><div class='line'></div><div class='line'>def fast_exp(a, n):</div><div class='line'>    if n == 0:</div><div class='line'>        return 1 </div><div class='line'>    if n == 1:</div><div class='line'>        return a </div><div class='line'>    else: </div><div class='line'>        res = 1</div><div class='line'>        b = fast_exp(a, n//2)</div><div class='line'>        res *= b*b </div><div class='line'>        if n % 2 == 1:</div><div class='line'>            res *= b </div><div class='line'>        return res</div></code></div></pre><!----> <p>Or in ocaml:</p> <!----><pre class="shiki monokai" ocaml="true"><div class="language-id">ocaml</div><div class='code-container'><code><div class='line'></div><div class='line'>let fast_exp base exp = </div><div class='line'>    let rec fast_exp_aux acc b e =</div><div class='line'>    if e &lt;= 0 then acc </div><div class='line'>    else if e mod 2 = 0 then fast_exp_aux acc (b*b) (e/2)</div><div class='line'>    else fast_exp_aux (acc*b) (b*b) (e/2) </div><div class='line'>    in fast_exp_aux 1 base exp</div></code></div></pre><!----> <p>Notice that we quickly turn the problem into a logarithmic problem. This is actually a feature of associativity, believe it or not! In general, for a semigroup <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi></mrow><annotation encoding="application/x-tex">S</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">S</span></span></span></span><!----></span> and binary operation <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>∗</mo><mo>:</mo><mi>S</mi><mo>×</mo><mi>S</mi><mo>→</mo><mi>S</mi></mrow><annotation encoding="application/x-tex">*: S \times S \to S</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∗</span><span class="mspace"></span><span class="mrel">:</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">S</span><span class="mspace"></span><span class="mbin">×</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">S</span><span class="mspace"></span><span class="mrel">→</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">S</span></span></span></span><!----></span>, when we write <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mn>1</mn></msub><mo>∗</mo><msub><mi>a</mi><mn>2</mn></msub><mo>∗</mo><mo>⋯</mo><mo>∗</mo><msub><mi>a</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">a_1 * a_2 * \cdots * a_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="minner">⋯</span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>, associativity gives us that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mn>1</mn></msub><mo>∗</mo><mo stretchy="false">(</mo><msub><mi>a</mi><mn>2</mn></msub><mo>∗</mo><mo>⋯</mo><mo>∗</mo><msub><mi>a</mi><mi>n</mi></msub><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><msub><mi>a</mi><mn>1</mn></msub><mo>∗</mo><mo>⋯</mo><msub><mi>a</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msub><mo stretchy="false">)</mo><mo>∗</mo><msub><mi>a</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">a_1 *(a_2 * \cdots * a_n) = (a_1 * \cdots a_{n-1}) *a_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="minner">⋯</span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="minner">⋯</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>. This is a signal that the order in which you evaluate doesn’t matter, so be aggressive and split the domain in half!</p> <h2 id="the-sparse-table"><a href="#the-sparse-table">The Sparse Table</a></h2> <p>That brings us to the humble Sparse Table. For problems where we are given an array <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span></span></span></span><!----></span>, queries <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Q</mi><mo>=</mo><mo stretchy="false">{</mo><mo stretchy="false">[</mo><msub><mi>L</mi><mi>i</mi></msub><mo separator="true">,</mo><msub><mi>R</mi><mi>i</mi></msub><mo stretchy="false">]</mo><msubsup><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mrow><mi>i</mi><mo>=</mo><mi>L</mi></mrow></msubsup></mrow><annotation encoding="application/x-tex">Q = \{ [L_i, R_i]\}_{i=1}^{i=L}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">Q</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">{[</span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">]</span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mathnormal mtight">L</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> and a binary operator <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>∗</mo></mrow><annotation encoding="application/x-tex">*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∗</span></span></span></span><!----></span>, where we can say that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>⊂</mo><mi>S</mi></mrow><annotation encoding="application/x-tex">A \subset S</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span><span class="mspace"></span><span class="mrel">⊂</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">S</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>S</mi><mo separator="true">,</mo><mo>∗</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(S, *)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord mathnormal">S</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">∗</span><span class="mclose">)</span></span></span></span><!----></span> forms a semigroup, we can speed up the computation of time here. I will use <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>A</mi><mo stretchy="false">[</mo><mi>L</mi><mo separator="true">,</mo><mi>R</mi><mo stretchy="false">]</mo><mo stretchy="false">)</mo><mo>=</mo><msub><mi>a</mi><mi>L</mi></msub><mo>∗</mo><mo>⋯</mo><mo>∗</mo><msub><mi>a</mi><mi>R</mi></msub></mrow><annotation encoding="application/x-tex">f(A[L,R]) = a_L * \cdots * a_R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mopen">[</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">R</span><span class="mclose">])</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">L</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="minner">⋯</span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">R</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> as a form of notation here to basically mean applying our binary operator across the range.</p> <p>Naively, you can just run that for each query, which would mean <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Q</mi></mrow><annotation encoding="application/x-tex">Q</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">Q</span></span></span></span><!----></span> queries that could be <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord mathnormal">N</span><span class="mclose">)</span></span></span></span><!----></span> steps, which means the time complexity here is <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo>∗</mo><mi>Q</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N*Q)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord mathnormal">N</span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">Q</span><span class="mclose">)</span></span></span></span><!----></span>, on the assumption that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>∗</mo></mrow><annotation encoding="application/x-tex">*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∗</span></span></span></span><!----></span> is a constant time operation. Not amazing. We ask ourselves, what can easily be computed? And can we reuse these building blocks?</p> <p><!--[-1--><img src="/assets/essence/sparse_table.svg" alt="Sparse Table Decomposition" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----> Yes you can. With powers of 2, we can break them up into smaller and smaller intervals. The diagram above tells us we have a natural relation:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>memo</mtext><mo stretchy="false">[</mo><mi>k</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo>=</mo><mi>f</mi><mo stretchy="false">(</mo><mtext>memo</mtext><mo stretchy="false">[</mo><mi>k</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mtext>memo</mtext><mo stretchy="false">[</mo><mi>k</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>i</mi><mo>+</mo><msup><mn>2</mn><mi>i</mi></msup><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\text{memo}[k][i] = f(\text{memo}[k-1][i], \text{memo}[k-1][i+2^i])</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord text"><span class="mord">memo</span></span><span class="mopen">[</span><span class="mord mathnormal">k</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord text"><span class="mord">memo</span></span><span class="mopen">[</span><span class="mord mathnormal">k</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord text"><span class="mord">memo</span></span><span class="mopen">[</span><span class="mord mathnormal">k</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span></span></span></span><span class="mclose">])</span></span></span></span></span><!----></div> <p>In english, this means we can compute the property of a <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mi>k</mi></msup></mrow><annotation encoding="application/x-tex">2^k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">k</span></span></span></span></span></span></span></span></span></span></span><!----></span> length interval by splitting it up into two evenly split <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mrow><mi>k</mi><mo>−</mo><mn>1</mn></mrow></msup></mrow><annotation encoding="application/x-tex">2^{k-1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">k</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span></span></span></span><!----></span> sized intervals. And in code:</p> <!----><pre class="shiki monokai" python="true"><div class="language-id">python</div><div class='code-container'><code><div class='line'>N = len(array)</div><div class='line'>K = ceil(math.log2(N))</div><div class='line'>memo = [[array[idx] if layer == 0 else 0 for idx in range(N)] for layer in range(K+1)]</div><div class='line'></div><div class='line'>for k in range(1, K): # O (log N )</div><div class='line'>    for idx in range(0, N): # O(N)</div><div class='line'>        if right := idx+int(2**(k-1)) &lt; N:</div><div class='line'>            memo[k][idx] = f(memo[k-1][idx], memo[k-1][right])</div></code></div></pre><!----> <p>In <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mi>log</mi><mo>⁡</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N \log N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord mathnormal">N</span><span class="mspace"></span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">N</span><span class="mclose">)</span></span></span></span><!----></span> steps, which is great, but not quite there for some <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">n\in \mathbb{N}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbb">N</span></span></span></span><!----></span> that isn’t a power of <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn></mrow><annotation encoding="application/x-tex">2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">2</span></span></span></span><!----></span>. We know that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><msub><mo>∑</mo><mrow><mi>i</mi><mo>∈</mo><mi>I</mi></mrow></msub><msup><mn>2</mn><mi>i</mi></msup></mrow><annotation encoding="application/x-tex">n = \sum_{i \in I} 2^i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop"><span class="mop op-symbol small-op">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight">I</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span></span></span></span></span></span></span><!----></span>, that is we can read off it’s binary representation to form a set of disjoint intervals that are powers of <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn></mrow><annotation encoding="application/x-tex">2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">2</span></span></span></span><!----></span> to get our result, which is <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>log</mi><mo>⁡</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(\log N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">N</span><span class="mclose">)</span></span></span></span><!----></span>. Recall that <code>(1 &lt;&lt; i) &amp; n</code> tells you whether the ith bit of <code>n</code> is on, so then we simply iterate over:</p> <!----><pre class="shiki monokai" python="true"><div class="language-id">python</div><div class='code-container'><code><div class='line'># Assume L is defined </div><div class='line'>value = None </div><div class='line'>query_len = R-L+1</div><div class='line'>for k in range(K):</div><div class='line'>    if (1 &lt;&lt; k) & query_len: # bit hit </div><div class='line'>        if value is None:</div><div class='line'>            value = memo[k][L]</div><div class='line'>        else:</div><div class='line'>            value = f(value, memo[k][L])</div><div class='line'>        L += int(2**k)</div><div class='line'></div><div class='line'></div></code></div></pre><!----> <p>And thus, we have a really cool way of remembering how sparse tables work. To summarise:</p> <ul><li>Compute intervals in powers of 2 in logarithmic time thanks to associativity</li> <li>Compute general interval lengths because of the binary representation</li></ul> <p>Also, it turns out, binary lifting is really just a sparse table implementation, but on trees. The binary operation in this case, is function composition, e.g <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>∘</mo><mi>f</mi><mo>∘</mo><mo>⋯</mo><mo>∘</mo><mi>f</mi><mo>=</mo><msup><mi>f</mi><mi>n</mi></msup><mo>=</mo><msup><mi>f</mi><mrow><mi>n</mi><mi mathvariant="normal">/</mi><mn>2</mn></mrow></msup><mo>∘</mo><msup><mi>f</mi><mrow><mi>n</mi><mi mathvariant="normal">/</mi><mn>2</mn></mrow></msup></mrow><annotation encoding="application/x-tex">f \circ f \circ \cdots \circ f = f^n = f^{n/2} \circ f^{n/2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mspace"></span><span class="mbin">∘</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mspace"></span><span class="mbin">∘</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="minner">⋯</span><span class="mspace"></span><span class="mbin">∘</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">f</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">f</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mtight">/2</span></span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mbin">∘</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">f</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mtight">/2</span></span></span></span></span></span></span></span></span></span></span></span><!----></span>, because you’re doing ‘jumps’. Neat!</p> <h2 id="idempotency"><a href="#idempotency">Idempotency</a></h2> <p>Idempotency is the idea that for some operation <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>∗</mo></mrow><annotation encoding="application/x-tex">*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∗</span></span></span></span><!----></span> we have that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∗</mo><mi>x</mi><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x * x = x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">x</span><span class="mspace"></span><span class="mbin">∗</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">x</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">x</span></span></span></span><!----></span>, i.e there is no change to the operation if applied repeatedly. In real world systems, such as payment systems, idempotency is a good property to ensure you don’t get double charged. It’s because of idempotency, that we can go from <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>log</mi><mo>⁡</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(\log N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">N</span><span class="mclose">)</span></span></span></span><!----></span> look-up to constant time look-up. In this case, we don’t really mind if there’s overlap in our intervals, so just pick the two intervals that tightly cover our desired query range <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mi>L</mi><mo separator="true">,</mo><mi>R</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[L,R]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">[</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">R</span><span class="mclose">]</span></span></span></span><!----></span>. More concretely, I claim that its given by this formula.</p> <p>Which operations are idempotent though?</p> <ul><li>minimum, maximum</li> <li>GCD, LCM</li></ul> <p>There are probably more, but note that these operations all form a semigroup. If our function doesn’t change under repeated application, this means we can reduce the time for a query to constant time, by picking <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mo>=</mo><mo stretchy="false">⌊</mo><mrow><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mrow><mi>R</mi><mo>−</mo><mi>L</mi><mo>+</mo><mn>1</mn></mrow></mrow><mo stretchy="false">⌋</mo></mrow><annotation encoding="application/x-tex">i = \lfloor{\log_2{R-L+1}} \rfloor</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">i</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">⌊</span><span class="mord"><span class="mop"><span class="mop">log</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">R</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord mathnormal">L</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span><span class="mord">1</span></span></span><span class="mclose">⌋</span></span></span></span><!----></span>, then computing <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mtext>memo</mtext><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>L</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mtext>memo</mtext><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>R</mi><mo>−</mo><msup><mn>2</mn><mi>i</mi></msup><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(\text{memo}[i][L], \text{memo}[i][R-2^i +1])</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord text"><span class="mord">memo</span></span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal">L</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord text"><span class="mord">memo</span></span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal">R</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">])</span></span></span></span><!----></span>. We illustrate this with a diagram.</p> <p><!--[-1--><img src="/assets/essence/sparse_table_idem.svg" alt="Idempotency and Sparse Tables" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>Bringing us to <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>Q</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(Q)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord mathnormal">Q</span><span class="mclose">)</span></span></span></span><!----></span> query time, and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mi>log</mi><mo>⁡</mo><mi>N</mi><mo>+</mo><mi>Q</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N \log N+Q)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord mathnormal">N</span><span class="mspace"></span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">N</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">Q</span><span class="mclose">)</span></span></span></span><!----></span> total time complexity.</p> <h2 id="prefix-sums"><a href="#prefix-sums">Prefix Sums</a></h2> <p>It turns out when your operation has more structure, e.g an inverse (so you have a group structure), you can actually use an easier technique, prefix+suffix sums. Implicitly, you need the idea of being able to cancel/invert an operation. For range sum queries, it suffices to instead compute the prefix and suffix sums, so that when you want <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>∑</mo><mi>A</mi><mo stretchy="false">[</mo><mi>L</mi><mo separator="true">,</mo><mi>R</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">\sum A[L,R]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mop op-symbol small-op">∑</span><span class="mspace"></span><span class="mord mathnormal">A</span><span class="mopen">[</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">R</span><span class="mclose">]</span></span></span></span><!----></span>, you can simply look at <code>sum(l,r) = prefix[R]-suffix[L-1]</code>.</p> <h2 id="problems"><a href="#problems">Problems</a></h2> <p>There are less problems on Leetcode that cover this format, so we head to the more competitively aligned programming sites. In general, I find CodeChef questions extremely confusing to read, and preferred the problems from CSES.</p> <h2 id="reflections"><a href="#reflections">Reflections</a></h2> <p>Python sucks for type checking, as it really lets you do stupid things that won’t raise an error, e.g indexing with a float (when raising to an exponent) won’t be immediately caught. Aside from this, once I had the intuition of associativity, I was mostly able to code up the implementation of a sparse table then recall that you can use <code>(1 &lt;&lt; i) &amp; n</code> to see if the ith bit was set. I did run into some intuition issues where I was computing the wrong ranges, but a good diagram really helps here. Additionally, other sites TLE even though my solution is within complexity :( - it’s easy enough to rewrite it in C++ fortunately as we don’t rely on any magical Python data structures.</p> <p>Also, did you know Excalidraw has libraries that you can import from? For instance I can import a System design library for icons that I would have otherwise crudely drawn, or for DSA!</p> <p>I found a relevant <a href="https://codeforces.com/blog/entry/79108" rel="nofollow noopener noreferrer external" target="_blank">Codeforces</a> article that outlines the insight that I found as well, while also generalising the idea to any monoid. I did mention that you can do this with a semigroup, but a monoid with identity makes this a bit nicer because you don’t need to deal with the weird empty edge case, and/or default initialise your values.</p> <h2 id="whats-next"><a href="#whats-next">What’s next?</a></h2> <p>I want to learn about Fenwick trees and Segment trees, as they go further, and allow you to work with modifications to your data structure. I suspect that some properties of a monoid may help here. I found that the easiest way to think about learning how a sparse table works is through understanding the underlying algebraic requirements for it to work. It feels like a motivator for why category theory matters here, and why we even compute a sparse table to start within.</p> <h2 id="resources"><a href="#resources">Resources</a></h2> <ul><li><a href="https://cp-algorithms.com/data_structures/sparse-table.html" rel="nofollow noopener noreferrer external" target="_blank">cp-algorithms - Sparse Table</a></li> <li><a href="https://seasalt.sh/words/dsa-sparse-tables" rel="nofollow noopener noreferrer external" target="_blank">sesalt.sh - 1 DS|A a day - Sparse Table</a></li></ul><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="blog" scheme="https://https:///?tags=blog" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Mining Yakuza 0 for Money Island Data]]></title>
    <link href="https://https:///yakuza0-archaeology" />
    <id>https://https:///yakuza0-archaeology</id>
    <published>2026-06-15T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <summary type="html"><![CDATA[Decoding Yakuza 0's data tables]]></summary>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><p>During Yakuza 0, Kiryu decides he wants to take over the real estate business in Kamurocho. Finishing the minigame means acquiring all the property, or shaking down Mr Shakedown. However, not all of the property you buy generate the same amount of cash, and you can often end up buying properties that cost more to run than they yield profit. In typical Sai-fashion, I wanted to know how Real Estate Royale actually pays out. The in-game UI tells you rank and share price, but not the underlying numbers, so I looked at the PC release files.</p> <h2 id="approach"><a href="#approach">Approach</a></h2> <p>Roughly in order:</p> <ol><li><strong>Index what’s on disk</strong>: file paths, sizes, which archive they came from. Paths live in <code>games/yakuza0/profile.yaml</code>.</li> <li><strong>Unpack</strong>: <a href="https://github.com/gibbed/Gibbed.Yakuza0" rel="nofollow noopener noreferrer external" target="_blank">Gibbed</a>’s tools for <code>stay.par</code> (minigames), <code>boot.par</code> (items/encounters), <code>battle.par</code> (combat dialogue and controller data).</li> <li><strong>Decode</strong>: most tables have a recognizable header (<code>20 07 03 19</code> descriptors, <code>*SB</code>/<code>*TB</code> fixed rows, <code>string_tbl</code> string pools, and a handful of battle-specific magics). Output goes to <code>data/tables/</code> as CSV + JSON.</li> <li><strong>Promote into a graph</strong>: interesting rows become entities with facts and links. Money Island was first; encounters and nawabari followed.</li></ol> <p>Locale files are parallel, not merged: <code>_bin_c</code> English, <code>_bin_j</code> Japanese, <code>_bin_k</code> Korean. Gameplay IDs stay stable; names come from whichever locale column you’re reading. In addition, Real Estate Royale is called Money Island.</p> <h2 id="graph-explorer"><a href="#graph-explorer">Graph explorer</a></h2> <p>Blue nodes are Money Island. Pink is encounters, amber nawabari, green items. Gray blobs are decoded table families that haven’t been promoted yet. Click a node to see the raw fields.</p> <div class="not-prose my-6 rounded-lg border border-base-300 overflow-hidden"><div class="flex h-full flex-col"><!--[-1--><!--]--> <div class="flex flex-wrap gap-3 border-b border-base-300 px-3 py-2 text-xs opacity-80"><!--[-1--><!--]--> <span class="ml-auto">Drag · scroll zoom · click node</span></div> <div class="relative min-h-0 flex-1"><div class="absolute inset-0"></div> <!--[-1--><!--]--></div></div><!----></div> <h2 id="whats-been-cdecoded"><a href="#whats-been-cdecoded">What’s been cdecoded</a></h2> <div class="prose-table-wrap overflow-x-auto mb-4 svelte-521o0"><table class="table svelte-521o0"><thead><tr><th>What</th><th align="right">Count</th></tr></thead> <tbody><tr><td>staypar tables decoded</td><td align="right">236</td></tr><tr><td>bootpar tables decoded</td><td align="right">432</td></tr><tr><td>battlepar tables decoded</td><td align="right">82</td></tr><tr><td>Total</td><td align="right">750</td></tr><tr><td>Graph entities</td><td align="right">743</td></tr><tr><td>Graph edges</td><td align="right">1149</td></tr></tbody><!----></table></div><!----> <p>Still sitting in JSON but not in the graph: the full item list, virtue shop, 374 activity entries, cabaret data. Thousands of other <code>.par</code> files in the install haven’t been touched.</p> <h2 id="real-estate-royale"><a href="#real-estate-royale">Real Estate Royale</a></h2> <p>The payout table is <code>money_island_shop.bin_c</code>: 50 rows, five areas with ten properties each. Each row has <code>profit_d</code> through <code>profit_s</code>. Comparing columns across shops gives clean rank multipliers:</p> <div class="prose-table-wrap overflow-x-auto mb-4 svelte-521o0"><table class="table svelte-521o0"><thead><tr><th>Rank</th><th align="right">Multiplier</th></tr></thead> <tbody><tr><td>D</td><td align="right">1.0×</td></tr><tr><td>C</td><td align="right">1.5×</td></tr><tr><td>B</td><td align="right">2.0×</td></tr><tr><td>A</td><td align="right">3.0×</td></tr><tr><td>S</td><td align="right">4.0×</td></tr></tbody><!----></table></div><!----> <p>Disco City Boy in Entertainment is the highest base earner at ¥38.4M per round at D-rank (¥153.6M at S). Kamuro Soba in Gambling is the lowest at ¥320K.</p> <p>All 50 properties from <code>money_island_shop.bin_c</code>, sorted by D-rank profit within each area. These are the numbers before rank upgrades: multiply by 1.5 / 2 / 3 / 4 for C / B / A / S.</p> <h3 id="entertainment-芸能"><a href="#entertainment-芸能">Entertainment (芸能)</a></h3> <div class="prose-table-wrap overflow-x-auto mb-4 svelte-521o0"><table class="table svelte-521o0"><thead><tr><th>Property</th><th align="right">D-rank profit</th></tr></thead> <tbody><tr><td>Disco City Boy</td><td align="right">¥38.4M</td></tr><tr><td>Hotel Blue Light</td><td align="right">¥31.2M</td></tr><tr><td>Telekura Rinrin-bo</td><td align="right">¥28.8M</td></tr><tr><td>Hotel Diamond Palace</td><td align="right">¥18.7M</td></tr><tr><td>Hotel Mermaid</td><td align="right">¥17.3M</td></tr><tr><td>Hotel White</td><td align="right">¥17.3M</td></tr><tr><td>Kamuro Hot Springs</td><td align="right">¥6.1M</td></tr><tr><td>Kogetsu Theater</td><td align="right">¥5M</td></tr><tr><td>Pocket Circuit Stadium</td><td align="right">¥4.2M</td></tr><tr><td>Tokiwa Restaurant</td><td align="right">¥2.9M</td></tr></tbody><!----></table></div><!----> <h3 id="gambling-賭博"><a href="#gambling-賭博">Gambling (賭博)</a></h3> <div class="prose-table-wrap overflow-x-auto mb-4 svelte-521o0"><table class="table svelte-521o0"><thead><tr><th>Property</th><th align="right">D-rank profit</th></tr></thead> <tbody><tr><td>Pachinko BIG STAR</td><td align="right">¥20.4M</td></tr><tr><td>Pachinko New Cosmos</td><td align="right">¥14M</td></tr><tr><td>Gibson Hall</td><td align="right">¥11.5M</td></tr><tr><td>Kamuro La Scala Cinema</td><td align="right">¥10.3M</td></tr><tr><td>TOKYO POPURI</td><td align="right">¥10.3M</td></tr><tr><td>Sanwa Leisure Hall</td><td align="right">¥10.1M</td></tr><tr><td>New Montmartre</td><td align="right">¥9.8M</td></tr><tr><td>NY Hot Dog</td><td align="right">¥2.6M</td></tr><tr><td>Mach Bowl</td><td align="right">¥1.8M</td></tr><tr><td>Kamuro Soba</td><td align="right">¥320K</td></tr></tbody><!----></table></div><!----> <h3 id="recreation-娯楽"><a href="#recreation-娯楽">Recreation (娯楽)</a></h3> <div class="prose-table-wrap overflow-x-auto mb-4 svelte-521o0"><table class="table svelte-521o0"><thead><tr><th>Property</th><th align="right">D-rank profit</th></tr></thead> <tbody><tr><td>Pachinko New Eden</td><td align="right">¥3.5M</td></tr><tr><td>Pachinko Marufuku</td><td align="right">¥3.5M</td></tr><tr><td>Health Wild Apple</td><td align="right">¥1.8M</td></tr><tr><td>Sukiyaki Muranaka</td><td align="right">¥1.6M</td></tr><tr><td>Harashima Design</td><td align="right">¥1.5M</td></tr><tr><td>Sushi Gin</td><td align="right">¥1.4M</td></tr><tr><td>Kamuro Health Plaza</td><td align="right">¥1.4M</td></tr><tr><td>Poppo Tenkaichi St.</td><td align="right">¥510K</td></tr><tr><td>Nyoki-Nyoki Academy</td><td align="right">¥405K</td></tr><tr><td>Yurizake</td><td align="right">¥390K</td></tr></tbody><!----></table></div><!----> <h3 id="digital-電脳"><a href="#digital-電脳">Digital (電脳)</a></h3> <div class="prose-table-wrap overflow-x-auto mb-4 svelte-521o0"><table class="table svelte-521o0"><thead><tr><th>Property</th><th align="right">D-rank profit</th></tr></thead> <tbody><tr><td>Pachinko 777</td><td align="right">¥4.9M</td></tr><tr><td>Pachinko Aloha</td><td align="right">¥4.7M</td></tr><tr><td>Lovely Bunny</td><td align="right">¥3.5M</td></tr><tr><td>Shokichi Camera</td><td align="right">¥2.3M</td></tr><tr><td>Asai Building No. 3</td><td align="right">¥1.9M</td></tr><tr><td>AMUSEMENT GAME YOU</td><td align="right">¥740K</td></tr><tr><td>Tenpo Sushi</td><td align="right">¥640K</td></tr><tr><td>HL SEGA Nakamichi St.</td><td align="right">¥640K</td></tr><tr><td>Beijing Chinese Eatery</td><td align="right">¥520K</td></tr><tr><td>DoReMiFa Zone</td><td align="right">¥280K</td></tr></tbody><!----></table></div><!----> <h3 id="adult-風俗"><a href="#adult-風俗">Adult (風俗)</a></h3> <div class="prose-table-wrap overflow-x-auto mb-4 svelte-521o0"><table class="table svelte-521o0"><thead><tr><th>Property</th><th align="right">D-rank profit</th></tr></thead> <tbody><tr><td>Cabaret Valentine</td><td align="right">¥10M</td></tr><tr><td>No-Panties BBQ</td><td align="right">¥7.8M</td></tr><tr><td>Arabia Records</td><td align="right">¥5.9M</td></tr><tr><td>Ogando Arts</td><td align="right">¥4.3M</td></tr><tr><td>Kamuro World Theater</td><td align="right">¥4.1M</td></tr><tr><td>Sexual Harassment Cop</td><td align="right">¥3.8M</td></tr><tr><td>Quartier Latin</td><td align="right">¥3.4M</td></tr><tr><td>Moscow Western Cuisine</td><td align="right">¥1.3M</td></tr><tr><td>Tontenshan</td><td align="right">¥1.2M</td></tr><tr><td>Hayashi Construction</td><td align="right">¥320K</td></tr></tbody><!----></table></div><!----> <h2 id="other-stuff-worth-noting"><a href="#other-stuff-worth-noting">Other stuff worth noting</a></h2> <p><strong>Encounters</strong>: spawn groups in <code>encounter_enemy_set</code>, loot weights in <code>encounter_drop_item</code>. Street drop pool 2 rolls Chestnut Shochu (栗焼酎) at 28%.</p> <p><strong>Nawabari</strong>: tenant names live in a <code>string_tbl</code> indirection table, not inline in the row. 320 shop types, keyed by row index.</p> <p><strong>Battlepar</strong>: 41 binaries decoded: 127 fighter controller entries (Kiryu through the zako archetypes), 568 wanderer speak symbols, 54 chase barks, 100 Coliseum endless arena fighters.</p> <h2 id="conclusion"><a href="#conclusion">Conclusion</a></h2> <p>I found this to be a rather easy exercise in datamining, as the tooling mostly existed for it already. But it does bring a thought, where you could use Cheat Engine/PINCE to look at the memory in-game, then look around the game binaries to make datamining an easier effort, especially for games where precise information is less available.</p> <p><!--[-1--><img src="/assets/offer.png" alt="I'll make an offer... in cash!" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="reverse-engineering" scheme="https://https:///?tags=reverse-engineering" />
    <category term="yakuza" scheme="https://https:///?tags=yakuza" />
    <category term="blog-post" scheme="https://https:///?tags=blog-post" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Essence of Recursion]]></title>
    <link href="https://https:///essence-recursion" />
    <id>https://https:///essence-recursion</id>
    <published>2026-06-14T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.251Z</updated>
    <summary type="html"><![CDATA[Framing recursion and dynamic programming as mathematical induction, with worked examples from linked lists and binary trees.]]></summary>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><p>Recursion is the idea of self-invocation until a base case is reached. Search algorithms like DFS fall out of it almost naturally, and when examined mathematically, it is just induction in disguise.</p> <h2 id="uses"><a href="#uses">Uses</a></h2> <ul><li>Recursive data structures (linked lists, trees, graphs)</li> <li>Dynamic programming (memoised recursion over a state space)</li></ul> <h2 id="recursion-as-mathematical-induction"><a href="#recursion-as-mathematical-induction">Recursion as Mathematical Induction</a></h2> <p>The idea of induction is as follows. Suppose I have some statement <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span> that I believe to be true over some domain, e.g. <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbb">N</span></span></span></span><!----></span>. The goal is to assume <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span> holds for some <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span></span></span></span><!----></span> and demonstrate that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(n+1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><!----></span> follows. The standard cookbook:</p> <ul><li>Prove the base case <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span><!----></span> holds</li> <li>Assume for <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><mi>k</mi></mrow><annotation encoding="application/x-tex">n = k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span></span></span></span><!----></span> that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mi>k</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(k)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mopen">(</span><span class="mord mathnormal">k</span><span class="mclose">)</span></span></span></span><!----></span> is true (or for strong induction, all <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>≤</mo><mi>k</mi></mrow><annotation encoding="application/x-tex">n \leq k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">≤</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span></span></span></span><!----></span>)</li> <li>Use that to demonstrate <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mi>k</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(k+1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mopen">(</span><span class="mord mathnormal">k</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><!----></span> also holds</li></ul> <p>One useful approach (taught in graph theory) is to start from <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mi>k</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(k+1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mopen">(</span><span class="mord mathnormal">k</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><!----></span> and reduce it to <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mi>k</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(k)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mopen">(</span><span class="mord mathnormal">k</span><span class="mclose">)</span></span></span></span><!----></span>, rather than building up. As an example:</p> <p><strong>Claim:</strong> A tree with <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span></span></span></span><!----></span> vertices has <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n - 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> edges.</p> <p><em>Proof by induction.</em> A tree is a connected, acyclic graph. In the base case <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n = 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span>, a single vertex has no edges, so <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span><!----></span> holds.</p> <p>Assume <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mi>k</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(k)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mopen">(</span><span class="mord mathnormal">k</span><span class="mclose">)</span></span></span></span><!----></span>: a tree with <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span></span></span></span><!----></span> vertices has <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">k - 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> edges. Now suppose <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi></mrow><annotation encoding="application/x-tex">T</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span></span></span></span><!----></span> is a tree with <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">k + 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> vertices. By a corollary (proved in the appendix below), every tree has at least two leaves; pick one, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">v_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>. Deleting <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">v_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> along with its single edge yields a tree <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>T</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">T&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">T</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span><!----></span> on <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span></span></span></span><!----></span> vertices; no cycles form because we removed a leaf, and connectivity is preserved because a leaf is not a cut vertex. By <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mi>k</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(k)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mopen">(</span><span class="mord mathnormal">k</span><span class="mclose">)</span></span></span></span><!----></span>, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>T</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">T&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">T</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span><!----></span> has <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">k - 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> edges, so <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∣</mi><mi>E</mi><mo stretchy="false">(</mo><mi>T</mi><mo stretchy="false">)</mo><mi mathvariant="normal">∣</mi><mo>=</mo><mi mathvariant="normal">∣</mi><mi>E</mi><mo stretchy="false">(</mo><msup><mi>T</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo stretchy="false">)</mo><mi mathvariant="normal">∣</mi><mo>+</mo><mn>1</mn><mo>=</mo><mi>k</mi></mrow><annotation encoding="application/x-tex">|E(T)| = |E(T&#x27;)| + 1 = k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∣</span><span class="mord mathnormal">E</span><span class="mopen">(</span><span class="mord mathnormal">T</span><span class="mclose">)</span><span class="mord">∣</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">∣</span><span class="mord mathnormal">E</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">T</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mord">∣</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span></span></span></span><!----></span>, which is what we needed to show. <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">□</mi></mrow><annotation encoding="application/x-tex">\square</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord amsrm">□</span></span></span></span><!----></span></p> <p>The key pattern: we relied on the truth of a smaller case to construct the present one. Recursion works the same way. When approaching a recursive problem, ask:</p> <ul><li><strong>Base case:</strong> what does the smallest valid input look like?</li> <li><strong>Sub-problem:</strong> what result from a smaller input do I need?</li> <li><strong>Construction:</strong> how do I assemble my answer from that result?</li></ul> <p>The challenge in recursion is usually the construction step. In DP, the harder question is choosing the right state representation. Both are fundamentally induction.</p> <h2 id="basic-examples"><a href="#basic-examples">Basic Examples</a></h2> <p><strong>Linked list sum.</strong> Applying the three questions:</p> <ul><li><em>Base case:</em> empty list → 0</li> <li><em>Sub-problem:</em> sum of the tail</li> <li><em>Construct:</em> add the head value to the tail sum</li></ul> <!----><pre class="shiki monokai" ocaml="true"><div class="language-id">ocaml</div><div class='code-container'><code><div class='line'>(* OCaml: pattern matching makes the structure explicit *)</div><div class='line'>let rec sum = function</div><div class='line'>    | [] -&gt; 0</div><div class='line'>    | head :: tail -&gt; head + sum tail</div></code></div></pre><!----> <p><strong>Coin change.</strong> Minimise the number of coins needed to make amount <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span></span></span></span><!----></span> from denominations <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi><mo>=</mo><mo stretchy="false">{</mo><msub><mi>C</mi><mn>1</mn></msub><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><msub><mi>C</mi><mi>k</mi></msub><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">C = \{C_1, \ldots, C_k\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">C</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="minner">…</span><span class="mspace"></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">}</span></span></span></span><!----></span>:</p> <ul><li><em>Base case:</em> <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">n = 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span> → 0 coins needed; <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>&lt;</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">n &lt; 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">&lt;</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span> → impossible</li> <li><em>Sub-problem:</em> the minimum coins for <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>−</mo><msub><mi>C</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">n - C_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> for each <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mi>i</mi></msub><mo>∈</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">C_i \in C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">C</span></span></span></span><!----></span></li> <li><em>Construct:</em> take 1 plus the minimum of those sub-problems</li></ul> <!----><pre class="shiki monokai" python="true"><div class="language-id">python</div><div class='code-container'><code><div class='line'>def coin_change(denoms, n):</div><div class='line'>    if n == 0:</div><div class='line'>        return 0</div><div class='line'>    return min(</div><div class='line'>        (1 + coin_change(denoms, n - c) for c in denoms if c &lt;= n),</div><div class='line'>        default=float('inf')</div><div class='line'>    )</div></code></div></pre><!----> <p>These examples track a single piece of state. Harder problems track multiple values, have more edge cases, or require careful thought about what the recursive call should return.</p> <h2 id="leetcode-twin-sum"><a href="#leetcode-twin-sum">Leetcode: Twin Sum</a></h2> <p><a href="https://leetcode.com/problems/maximum-twin-sum-of-a-linked-list/description/" rel="nofollow noopener noreferrer external" target="_blank">Leetcode 2130: Maximum Twin Sum of a LinkedList</a>: pair the first and last nodes, second and second-last, and so on, then return the maximum pair sum.</p> <p>A naive approach (collect the first half into an array, then walk the second half) works but is inelegant. Three cleaner approaches:</p> <ul><li>Reverse the first half in place and iterate together</li> <li>Hare-and-tortoise to find the midpoint, then reverse</li> <li>A <strong>zipper</strong>: descend recursively to the end, then walk the front pointer forward as the call stack unwinds</li></ul> <p>The zipper approach fell out most naturally to me. The key insight: on the way back up the call stack, we’re naturally iterating the <em>back</em> pointer from last to first, while the <em>front</em> pointer steps forward.</p> <p><!--[-1--><img src="/assets/essence/rec_twin_sum.svg" alt="Twin Sum zipper diagram" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>The recursive function carries the current front node and returns the updated front pointer together with the running maximum:</p> <!----><pre class="shiki monokai" python="true"><div class="language-id">python</div><div class='code-container'><code><div class='line'>def recurse(front, back, max_val):</div><div class='line'>    if back.next is None:</div><div class='line'>        # base: at the last node, form the first pair</div><div class='line'>        return max(max_val, back.val + front.val), front.next</div><div class='line'></div><div class='line'>    best_val, next_front = recurse(front, back.next, max_val)</div><div class='line'>    # unwinding: back is now moving backwards; front advances via next_front</div><div class='line'>    return max(best_val, next_front.val + back.val), next_front.next</div></code></div></pre><!----> <p>At every frame on the way up, <code>back</code> is one step closer to the front while <code>next_front</code> steps forward; they meet in the middle.</p> <h2 id="practice-problems"><a href="#practice-problems">Practice Problems</a></h2> <p><strong>Linked lists</strong></p> <ul><li><a href="https://leetcode.com/problems/palindrome-linked-list/description/" rel="nofollow noopener noreferrer external" target="_blank">234. Palindrome Linked List</a></li> <li><a href="https://leetcode.com/problems/reverse-linked-list/description/" rel="nofollow noopener noreferrer external" target="_blank">206. Reverse Linked List</a></li> <li><a href="https://leetcode.com/problems/swap-nodes-in-pairs/description/" rel="nofollow noopener noreferrer external" target="_blank">24. Swap Nodes in Pairs</a></li> <li><a href="https://leetcode.com/problems/reverse-nodes-in-k-group/description/" rel="nofollow noopener noreferrer external" target="_blank">25. Reverse Nodes in k-Group</a></li></ul> <p><strong>Trees</strong></p> <ul><li><a href="https://leetcode.com/problems/maximum-depth-of-binary-tree/description/" rel="nofollow noopener noreferrer external" target="_blank">104. Maximum Depth of Binary Tree</a></li> <li><a href="https://leetcode.com/problems/balanced-binary-tree/description/" rel="nofollow noopener noreferrer external" target="_blank">110. Balanced Binary Tree</a></li> <li><a href="https://leetcode.com/problems/binary-tree-maximum-path-sum/description/" rel="nofollow noopener noreferrer external" target="_blank">124. Binary Tree Maximum Path Sum</a></li> <li><a href="https://leetcode.com/problems/longest-univalue-path/description/" rel="nofollow noopener noreferrer external" target="_blank">687. Longest Univalue Path</a></li></ul> <h2 id="worked-reverse-nodes-in-k-group"><a href="#worked-reverse-nodes-in-k-group">Worked: Reverse Nodes in k-Group</a></h2> <p>The trick is to isolate the recursive leap of faith. Assume the suffix starting from position <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">k+1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> is already correctly reversed. Then all you need to do is reverse the current <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span></span></span></span><!----></span>-group and attach it to that sorted suffix: iterate <code>curr → prev</code> while threading <code>curr → next</code>.</p> <h2 id="worked-binary-tree-maximum-path-sum"><a href="#worked-binary-tree-maximum-path-sum">Worked: Binary Tree Maximum Path Sum</a></h2> <p>This one tripped me up because you track two different things:</p> <ul><li><strong>Global best:</strong> the best path seen anywhere in the tree (updated at each node)</li> <li><strong>Local best:</strong> the best <em>continuous</em> path rooted at this node that a <em>parent</em> can extend</li></ul> <p>Applying the template:</p> <ul><li><em>Base case:</em> null node contributes 0; a leaf is just its value</li> <li><em>Sub-problem:</em> left and right subtrees each give a global best and a local best (one-sided path)</li> <li><em>Construct:</em> try stitching <code>L + node + R</code> to update the global best; the local best is <code>node + max(L, R, 0)</code></li></ul> <p>Keep your variable names precise: confusing <code>l_best</code> (global best from left subtree) with <code>l_path</code> (best path rooted at left child) is an easy way to get wrong answers.</p> <p><!--[-1--><img src="/assets/essence/rec_path_sum.svg" alt="Maximum path sum diagram" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p><strong>Longest Univalue Path</strong> follows the same pattern, but the “stitching” condition becomes value equality rather than unconstrained addition. Watch your sentinel values: if node values can be negative, don’t use <code>-1</code> as “impossible”.</p> <h2 id="how-rusty-was-i"><a href="#how-rusty-was-i">How Rusty Was I?</a></h2> <p>As a form of self-humiliation, a log of the mistakes that actually happened:</p> <ul><li>Used <code>|</code> instead of <code>&amp;</code> in a boolean expression</li> <li>Missing brackets around an inequality comparison</li> <li>Forgot to <code>return</code> the recursive call (classic)</li> <li>Returned the whole tuple where only one element was needed</li> <li>In Swap Nodes in Pairs: <code>head.next, head = head, head.next</code> and <code>head, head.next = head.next, head</code> are <strong>not</strong> the same (Python evaluates the right-hand side first as a tuple)</li> <li>Struggled to see why you need a temporary when swapping</li> <li>The bracket placement in <code>balanced = (abs(l_height - r_height) &lt;= 1) &amp; l_bal &amp; r_bal</code></li> <li>Mixed up argument order in a recursive call</li> <li>Used the global best from the left subtree to compute the best continuous sum (these are different things)</li> <li>Used a sentinel of <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">-1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">−</span><span class="mord">1</span></span></span></span><!----></span> for Longest Univalue Path when node values lie in <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mo>−</mo><mn>1000</mn><mo separator="true">,</mo><mn>1000</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[-1000, 1000]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">[</span><span class="mord">−</span><span class="mord">1000</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">1000</span><span class="mclose">]</span></span></span></span><!----></span></li></ul> <p>Despite all that, a few problems was enough to shake the rust off. The main lesson: for trees, you often want to compute a global property while threading local subtree state upwards. Linked list problems often involve a second pointer tracking a different part of the list.</p> <h2 id="appendix-every-tree-has-at-least-two-leaves"><a href="#appendix-every-tree-has-at-least-two-leaves">Appendix: Every Tree Has at Least Two Leaves</a></h2> <p>For a tree <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi></mrow><annotation encoding="application/x-tex">T</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span></span></span></span><!----></span> (connected, acyclic graph) with <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>≥</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">n \geq 2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">≥</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">2</span></span></span></span><!----></span>, we claim it has at least one leaf (a vertex of degree 1). Let <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo>=</mo><mo stretchy="false">(</mo><mi>u</mi><mo separator="true">,</mo><msub><mi>v</mi><mn>1</mn></msub><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><mi>v</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P = (u, v_1, \ldots, v)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="minner">…</span><span class="mspace"></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">v</span><span class="mclose">)</span></span></span></span><!----></span> be a maximal path in <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi></mrow><annotation encoding="application/x-tex">T</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span></span></span></span><!----></span>, i.e. one that cannot be extended at either end.</p> <p>Because <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi></mrow><annotation encoding="application/x-tex">P</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span></span></span></span><!----></span> is maximal, no neighbour of <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">u</span></span></span></span><!----></span> lies outside <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi></mrow><annotation encoding="application/x-tex">P</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span></span></span></span><!----></span> (otherwise <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi></mrow><annotation encoding="application/x-tex">P</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span></span></span></span><!----></span> could be extended). And no neighbour of <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">u</span></span></span></span><!----></span> lies <em>inside</em> <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi></mrow><annotation encoding="application/x-tex">P</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">P</span></span></span></span><!----></span> either: if some <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mo>∈</mo><mi>N</mi><mo stretchy="false">(</mo><mi>u</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">s \in N(u)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">s</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">N</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mclose">)</span></span></span></span><!----></span> were adjacent to an interior vertex <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">v_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>, we could form a cycle through <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi></mrow><annotation encoding="application/x-tex">s</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">s</span></span></span></span><!----></span>, contradicting acyclicity. Both cases are illustrated below.</p> <p><!--[-1--><img src="/assets/essence/rec_maxpath.svg" alt="Maximal path proof" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>Therefore <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>deg</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>u</mi><mo stretchy="false">)</mo><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\deg(u) = 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mop">deg</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span>, i.e. <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi></mrow><annotation encoding="application/x-tex">u</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">u</span></span></span></span><!----></span> is a leaf. The same argument applies to <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi></mrow><annotation encoding="application/x-tex">v</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">v</span></span></span></span><!----></span>, giving at least two leaves. <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">□</mi></mrow><annotation encoding="application/x-tex">\square</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord amsrm">□</span></span></span></span><!----></span></p> <h2 id="conclusion"><a href="#conclusion">Conclusion</a></h2> <p>Recursion, dynamic programming, DFS, and most tree/linked-list problems are all induction over a state space. Internalising that framing makes it much easier to construct solutions systematically: identify the base case, decide what the recursive call should return, and build the answer from there.</p><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="recursion" scheme="https://https:///?tags=recursion" />
    <category term="dynamic-programming" scheme="https://https:///?tags=dynamic-programming" />
    <category term="linked-lists" scheme="https://https:///?tags=linked-lists" />
    <category term="trees" scheme="https://https:///?tags=trees" />
    <category term="leetcode" scheme="https://https:///?tags=leetcode" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Competitive Programming]]></title>
    <link href="https://https:///growth/2026/competitive-programming" />
    <id>https://https:///growth/2026/competitive-programming</id>
    <published>2026-01-10T00:00:00.000Z</published>
    <updated>2026-01-10T00:00:00.000Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="overview"><a href="#overview">Overview</a></h2> <p>Page for any competitive programming algorithms and techniques I learn.</p> <h2 id="edit-distance-revisited-1102026"><a href="#edit-distance-revisited-1102026">Edit Distance Revisited (1/10/2026)</a></h2> <p>A reminder, that for any dynamic programming problem, is that we can think of it as a mathematical optimisation problem, which is defined by</p> <ul><li>Overlapping Subproblems</li> <li>Optimal Substructure</li></ul> <p>We think about the recurrence that links different states, and define a state space that’s helpful for our problem. In the case of edit distance, for strings <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi></mrow><annotation encoding="application/x-tex">B</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">B</span></span></span></span><!----></span>, we defined the state <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi><mo stretchy="false">(</mo><mi>i</mi><mo separator="true">,</mo><mi>j</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">D(i,j)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">D</span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">j</span><span class="mclose">)</span></span></span></span><!----></span> as the minimum edit distance between the prefixes <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo stretchy="false">[</mo><mn>0</mn><mo>:</mo><mi>i</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">A[0:i]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span><span class="mopen">[</span><span class="mord">0</span><span class="mspace"></span><span class="mrel">:</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">i</span><span class="mclose">]</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi><mo stretchy="false">[</mo><mn>0</mn><mo>:</mo><mi>j</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">B[0:j]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">B</span><span class="mopen">[</span><span class="mord">0</span><span class="mspace"></span><span class="mrel">:</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">j</span><span class="mclose">]</span></span></span></span><!----></span>. That way, our solution is simply <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi><mo stretchy="false">(</mo><mi mathvariant="normal">∣</mi><mi>A</mi><mi mathvariant="normal">∣</mi><mo separator="true">,</mo><mi mathvariant="normal">∣</mi><mi>B</mi><mi mathvariant="normal">∣</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">D(|A|, |B|)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">D</span><span class="mopen">(</span><span class="mord">∣</span><span class="mord mathnormal">A</span><span class="mord">∣</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">∣</span><span class="mord mathnormal">B</span><span class="mord">∣</span><span class="mclose">)</span></span></span></span><!----></span>.</p> <p>We define the recurrence as:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>D</mi><mo stretchy="false">(</mo><mi>i</mi><mo separator="true">,</mo><mi>j</mi><mo stretchy="false">)</mo><mo>=</mo><mi>min</mi><mo>⁡</mo><mrow><mo fence="true">{</mo><mtable rowspacing="0.36em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>D</mi><mo stretchy="false">(</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo separator="true">,</mo><mi>j</mi><mo stretchy="false">)</mo><mo>+</mo><mn>1</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mtext>(deletion)</mtext></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>D</mi><mo stretchy="false">(</mo><mi>i</mi><mo separator="true">,</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>+</mo><mn>1</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mtext>(insertion)</mtext></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>D</mi><mo stretchy="false">(</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo separator="true">,</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>+</mo><mtext>cost</mtext><mo stretchy="false">(</mo><mi>A</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>B</mi><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mtext>(substitution)</mtext></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">D(i,j) = \min \begin{cases}   D(i-1, j) + 1 &amp; \text{(deletion)} \\  D(i, j-1) + 1 &amp; \text{(insertion)} \\  D(i-1, j-1) + \text{cost}(A[i], B[j]) &amp; \text{(substitution)}\end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">D</span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">j</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop">min</span><span class="mspace"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="delimsizinginner delim-size4">⎩</span></span><span class="pstrut"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span><span class="pstrut"><span class="delimsizinginner delim-size4">⎨</span></span><span class="pstrut"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span><span class="pstrut"><span class="delimsizinginner delim-size4">⎧</span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">D</span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">j</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span><span class="mord">1</span></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">D</span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">j</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span><span class="mord">1</span></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">D</span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">j</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span><span class="mord text"><span class="mord">cost</span></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">B</span><span class="mopen">[</span><span class="mord mathnormal">j</span><span class="mclose">])</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="arraycolsep"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord text"><span class="mord">(deletion)</span></span></span></span><span class="pstrut"><span class="mord"><span class="mord text"><span class="mord">(insertion)</span></span></span></span><span class="pstrut"><span class="mord"><span class="mord text"><span class="mord">(substitution)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span><!----></div> <p>Here, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext>cost</mtext><mo stretchy="false">(</mo><mi>A</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>B</mi><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\text{cost}(A[i], B[j])</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord text"><span class="mord">cost</span></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">B</span><span class="mopen">[</span><span class="mord mathnormal">j</span><span class="mclose">])</span></span></span></span><!----></span> is <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn></mrow><annotation encoding="application/x-tex">0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span> if the characters are the same, and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn></mrow><annotation encoding="application/x-tex">1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> otherwise. If you think about the recurrence, cover the character at position <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">i</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>j</mi></mrow><annotation encoding="application/x-tex">j</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">j</span></span></span></span><!----></span> in <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi></mrow><annotation encoding="application/x-tex">B</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">B</span></span></span></span><!----></span> respectively. We can get to that point via insertion <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>i</mi><mo separator="true">,</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(i,j-1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">j</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><!----></span>, deletion <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo separator="true">,</mo><mi>j</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(i-1,j)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">j</span><span class="mclose">)</span></span></span></span><!----></span>, or substituting a character <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo separator="true">,</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(i-1,j-1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">j</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><!----></span>.</p> <div class="annotated-code not-prose svelte-1cwmi07"><h2 class="renderer-title svelte-1cwmi07"></h2> <div class="renderer-container svelte-1cwmi07"><!--[0--><div class="loading-state svelte-1cwmi07">Loading content...</div><!--]--></div></div><!----> <h1 id="trees"><a href="#trees">Trees</a></h1> <p>To motivate the many ways we can solve LCA, we start with a naive implementation.</p> <h2 id="naive-lca"><a href="#naive-lca">Naive LCA</a></h2> <h2 id="binary-lifting"><a href="#binary-lifting">Binary Lifting</a></h2> <p>Think of this as an amazing teleportation technique. If we have the ability to ascend <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mi>k</mi></msup></mrow><annotation encoding="application/x-tex">2^k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">k</span></span></span></span></span></span></span></span></span></span></span><!----></span> levels in one jump, then we can reach any ancestor in <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>log</mi><mo>⁡</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(\log N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">N</span><span class="mclose">)</span></span></span></span><!----></span> jumps. After which, we can then trivially iterate on the remaining ones. As an example, if we want to go up <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>13</mn></mrow><annotation encoding="application/x-tex">13</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">13</span></span></span></span><!----></span> levels, we can do <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>+</mo><mn>4</mn><mo>+</mo><mn>8</mn></mrow><annotation encoding="application/x-tex">1+4+8</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">4</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">8</span></span></span></span><!----></span> jumps, which is <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>3</mn></mrow><annotation encoding="application/x-tex">3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">3</span></span></span></span><!----></span> jumps total. We look at the first ancestor of our node, then the <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">2^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><!----></span> ancestor of that node, and then the <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mn>3</mn></msup></mrow><annotation encoding="application/x-tex">2^3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span></span></span></span><!----></span> ancestor of that node.</p> <p>All of this corresponds to looking at a table repeatedly until we get to our destination.</p> <div class="annotated-code not-prose svelte-1cwmi07"><h2 class="renderer-title svelte-1cwmi07"></h2> <div class="renderer-container svelte-1cwmi07"><!--[0--><div class="loading-state svelte-1cwmi07">Loading content...</div><!--]--></div></div><!----> <h2 id="resources"><a href="#resources">Resources</a></h2> <ul><li>Resource 1</li> <li>Resource 2</li></ul><!----><!--]--><!----><!----><!--]-->]]>
    </content>
  </entry>
  <entry>
    <title type="html"><![CDATA[Classical Mechanics]]></title>
    <link href="https://https:///growth/2026/classical-mechanics" />
    <id>https://https:///growth/2026/classical-mechanics</id>
    <published>2026-01-02T00:00:00.000Z</published>
    <updated>2026-01-02T00:00:00.000Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="overview"><a href="#overview">Overview</a></h2> <p>The study of classical mechanics involves understanding the motion of bodies under the influence of forces. We assume no relativistic effects are at play and study simple systems using Newtonian, Lagrangian, and Hamiltonian frameworks.</p> <h2 id="learning-path"><a href="#learning-path">Learning Path</a></h2> <p>Progress through Taylor’s <em>Classical Mechanics</em>.</p> <h2 id="resources"><a href="#resources">Resources</a></h2> <ul><li><a href="https://www.amazon.com/Classical-Mechanics-John-R-Taylor/dp/189138922X" rel="nofollow noopener noreferrer external" target="_blank">Classical Mechanics - John R. Taylor</a></li></ul> <h2 id="newtons-laws-of-motion"><a href="#newtons-laws-of-motion">Newton’s Laws of Motion</a></h2> <p>We first establish the Cartesian coordinate system with basis vectors <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>e</mi><mn>2</mn></msub><mo separator="true">,</mo><msub><mi>e</mi><mn>3</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(e_1, e_2, e_3)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span> and position vector <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">r</mi><mo>=</mo><mi>x</mi><msub><mi>e</mi><mn>1</mn></msub><mo>+</mo><mi>y</mi><msub><mi>e</mi><mn>2</mn></msub><mo>+</mo><mi>z</mi><msub><mi>e</mi><mn>3</mn></msub></mrow><annotation encoding="application/x-tex">\mathbf{r} = x e_1 + y e_2 + z e_3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">r</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">x</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">y</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">z</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> which is written as <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo separator="true">,</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(x,y,z)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">y</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">z</span><span class="mclose">)</span></span></span></span><!----></span>. We have all the standard vector operations for <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi mathvariant="double-struck">R</mi><mn>3</mn></msup></mrow><annotation encoding="application/x-tex">\mathbb{R}^3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span></span></span></span><!----></span> such as dot product <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">a</mi><mo>⋅</mo><mi mathvariant="bold">b</mi></mrow><annotation encoding="application/x-tex">\mathbf{a} \cdot \mathbf{b}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">a</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbf">b</span></span></span></span><!----></span> and cross product <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">a</mi><mo>×</mo><mi mathvariant="bold">b</mi></mrow><annotation encoding="application/x-tex">\mathbf{a} \times \mathbf{b}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">a</span><span class="mspace"></span><span class="mbin">×</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbf">b</span></span></span></span><!----></span>.</p> <p>For instance, consider a force <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">F</mi></mrow><annotation encoding="application/x-tex">\mathbf{F}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">F</span></span></span></span><!----></span> acting about the origin (like a stone). The torque <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">Γ</mi><mo>=</mo><mi>r</mi><mo>×</mo><mi mathvariant="bold">F</mi></mrow><annotation encoding="application/x-tex">\mathbf{\Gamma} = r \times \mathbf{F}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">Γ</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">r</span><span class="mspace"></span><span class="mbin">×</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbf">F</span></span></span></span><!----></span> is defined as such.</p> <p>We then have a vector valued function <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">r</mi><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><mo separator="true">,</mo><mi>y</mi><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><mo separator="true">,</mo><mi>z</mi><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathbf{r}(t) = (x(t), y(t), z(t))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">r</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">y</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">z</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">))</span></span></span></span><!----></span> which can be differentiated and integrated with minimal issue. Most importantly, we note that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">r</mi><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><mo>=</mo><mi>x</mi><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><msub><mi>e</mi><mn>1</mn></msub><mo>+</mo><mi>y</mi><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><msub><mi>e</mi><mn>2</mn></msub><mo>+</mo><mi>z</mi><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><msub><mi>e</mi><mn>3</mn></msub></mrow><annotation encoding="application/x-tex">\mathbf{r}(t) = x(t) e_1 + y(t) e_2 + z(t) e_3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">r</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">y</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">z</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>, and so when we differentiate wrt time <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>t</mi></mrow><annotation encoding="application/x-tex">t</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">t</span></span></span></span><!----></span>, each term is constant, and so you have three terms. This is special to the Cartesian coordinate system, and doesn’t hold for the Polar Coordinate system.</p> <h2 id="first-and-second-law-of-motion"><a href="#first-and-second-law-of-motion">First and Second Law of Motion</a></h2> <p>The First Law of Motion states that an object with no forces acting on it will maintain constant velocity, i.e <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">F</mi><mo>=</mo><mn>0</mn><mtext>  </mtext><mo>⟹</mo><mtext>  </mtext><mfrac><mrow><msup><mi>d</mi><mn>2</mn></msup><mi mathvariant="bold">r</mi></mrow><mrow><mi>d</mi><msup><mi>t</mi><mn>2</mn></msup></mrow></mfrac><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\mathbf{F} = 0 \implies \frac{d^2 \mathbf{r}}{dt^2} = 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">F</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span><span class="mspace"></span><span class="mspace"></span><span class="mrel">⟹</span><span class="mspace"></span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mathbf mtight">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span>.</p> <p>And more generally, for an object with mass <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">m</span></span></span></span><!----></span> and force <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">F</mi></mrow><annotation encoding="application/x-tex">\mathbf{F}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">F</span></span></span></span><!----></span> acting on it, we have the Second Law of Motion:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="bold">F</mi><mo>=</mo><mi>m</mi><mfrac><mrow><msup><mi>d</mi><mn>2</mn></msup><mi mathvariant="bold">r</mi></mrow><mrow><mi>d</mi><msup><mi>t</mi><mn>2</mn></msup></mrow></mfrac><mo>=</mo><mi>m</mi><mi mathvariant="bold">a</mi></mrow><annotation encoding="application/x-tex">\mathbf{F} = m \frac{d^2 \mathbf{r}}{dt^2} = m \mathbf{a}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">F</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">m</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">d</span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mathbf">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">m</span><span class="mord mathbf">a</span></span></span></span></span><!----></div> <p>Recalling that momentum is defined as <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">p</mi><mo>=</mo><mi>m</mi><mi mathvariant="bold">v</mi></mrow><annotation encoding="application/x-tex">\mathbf{p} = m \mathbf{v}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">p</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">m</span><span class="mord mathbf">v</span></span></span></span><!----></span>, we also have that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">F</mi><mo>=</mo><mfrac><mrow><mi>d</mi><mi mathvariant="bold">p</mi></mrow><mrow><mi>d</mi><mi>t</mi></mrow></mfrac></mrow><annotation encoding="application/x-tex">\mathbf{F} = \frac{d \mathbf{p}}{dt}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">F</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">t</span></span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathbf mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span><!----></span>.</p> <h2 id="inertial-frames"><a href="#inertial-frames">Inertial Frames</a></h2> <p>Note that the laws of motion only hold in inertial frames of reference, which are frames that are either at rest or moving with constant velocity. The easiest example of a non-inertial frame is an object moving inside a train that is accelerating. In such a frame, fictitious forces (like the Coriolis force) may appear to act on objects.</p> <h2 id="third-law-of-motion"><a href="#third-law-of-motion">Third Law of Motion</a></h2> <p>For a pair of objects <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi></mrow><annotation encoding="application/x-tex">B</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">B</span></span></span></span><!----></span>, the force exerted by <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span></span></span></span><!----></span> on <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi></mrow><annotation encoding="application/x-tex">B</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">B</span></span></span></span><!----></span> is equal in magnitude and opposite in direction to the force exerted by <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi></mrow><annotation encoding="application/x-tex">B</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">B</span></span></span></span><!----></span> on <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span></span></span></span><!----></span>, i.e <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mrow><mi>A</mi><mi>B</mi></mrow></msub><mo>=</mo><mo>−</mo><msub><mi>F</mi><mrow><mi>B</mi><mi>A</mi></mrow></msub></mrow><annotation encoding="application/x-tex">F_{AB} = - F_{BA}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="mord mathnormal mtight">B</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">−</span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">B</span><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>.</p> <p>Now consider a system of two objects <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi></mrow><annotation encoding="application/x-tex">B</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">B</span></span></span></span><!----></span>, we can write out their net forces as <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>F</mi><mi>A</mi><mrow><mi>n</mi><mi>e</mi><mi>t</mi></mrow></msubsup><mo>=</mo><msub><mi>F</mi><mrow><mi>A</mi><mi>B</mi></mrow></msub><mo>+</mo><msubsup><mi>F</mi><mi>A</mi><mrow><mi>e</mi><mi>x</mi><mi>t</mi></mrow></msubsup></mrow><annotation encoding="application/x-tex">F_A^{net} = F_{AB} + F_{A}^{ext}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="mord mathnormal mtight">B</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>F</mi><mi>B</mi><mrow><mi>n</mi><mi>e</mi><mi>t</mi></mrow></msubsup><mo>=</mo><msub><mi>F</mi><mrow><mi>B</mi><mi>A</mi></mrow></msub><mo>+</mo><msubsup><mi>F</mi><mi>B</mi><mrow><mi>e</mi><mi>x</mi><mi>t</mi></mrow></msubsup></mrow><annotation encoding="application/x-tex">F_B^{net} = F_{BA} + F_{B}^{ext}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">B</span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">B</span><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">B</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>. Adding these two equations, we have:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msubsup><mi>F</mi><mi>A</mi><mrow><mi>n</mi><mi>e</mi><mi>t</mi></mrow></msubsup><mo>+</mo><msubsup><mi>F</mi><mi>B</mi><mrow><mi>n</mi><mi>e</mi><mi>t</mi></mrow></msubsup><mo>=</mo><msubsup><mi>F</mi><mi>A</mi><mrow><mi>e</mi><mi>x</mi><mi>t</mi></mrow></msubsup><mo>+</mo><msubsup><mi>F</mi><mi>B</mi><mrow><mi>e</mi><mi>x</mi><mi>t</mi></mrow></msubsup><mo>=</mo><msub><mi>F</mi><mrow><mi>e</mi><mi>x</mi><mi>t</mi></mrow></msub></mrow><annotation encoding="application/x-tex">F_{A}^{net} + F_{B}^{net} = F_{A}^{ext} + F_{B}^{ext} = F_{ext}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">B</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">B</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><!----></div> <p>If <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mrow><mi>e</mi><mi>x</mi><mi>t</mi></mrow></msub><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">F_{ext} = 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span>, then we have <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>F</mi><mi>A</mi><mrow><mi>n</mi><mi>e</mi><mi>t</mi></mrow></msubsup><mo>+</mo><msubsup><mi>F</mi><mi>B</mi><mrow><mi>n</mi><mi>e</mi><mi>t</mi></mrow></msubsup><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">F_{A}^{net} + F_{B}^{net} = 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">B</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span>, which implies that the total momentum of the system is conserved. Interestingly enough, the third law doesn’t even always hold up in classical mechanics, for instance, in electromagnetic interactions. Take two positive charges moving orthogonally to each other, the magnetic forces they exert on each other do not satisfy the third law by the Right Hand Rule.</p> <h2 id="polar-newton"><a href="#polar-newton">Polar Newton</a></h2> <p>Recall <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>r</mi><mn>2</mn></msup><mo>=</mo><msup><mi>x</mi><mn>2</mn></msup><mo>+</mo><msup><mi>y</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">r^2 = x^2 + y^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">r</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><!----></span>, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>=</mo><mi>r</mi><mi>cos</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x = r \cos(\theta)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">x</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">r</span><span class="mspace"></span><span class="mop">cos</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span></span></span></span><!----></span>, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mo>=</mo><mi>r</mi><mi>sin</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">y = r \sin(\theta)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">y</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">r</span><span class="mspace"></span><span class="mop">sin</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span></span></span></span><!----></span>, and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi><mo>=</mo><msup><mrow><mi>tan</mi><mo>⁡</mo></mrow><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo stretchy="false">(</mo><mi>y</mi><mi mathvariant="normal">/</mi><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\theta = \tan^{-1}(y/x)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">θ</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop"><span class="mop">tan</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">y</span><span class="mord">/</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span><!----></span>. We have new unit vectors <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>r</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{r}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">r</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>θ</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{\theta}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">θ</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span></span></span></span><!----></span> defined as:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mover accent="true"><mi>r</mi><mo>^</mo></mover><mo>=</mo><mi>cos</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><msub><mi>e</mi><mn>1</mn></msub><mo>+</mo><mi>sin</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><msub><mi>e</mi><mn>2</mn></msub><mo separator="true">,</mo><mspace width="1em"/><mover accent="true"><mi>θ</mi><mo>^</mo></mover><mo>=</mo><mo>−</mo><mi>sin</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><msub><mi>e</mi><mn>1</mn></msub><mo>+</mo><mi>cos</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">\hat{r} = \cos(\theta) e_1 + \sin(\theta) e_2, \quad \hat{\theta} = -\sin(\theta) e_1 + \cos(\theta) e_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">r</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop">cos</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop">sin</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mspace"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">θ</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">−</span><span class="mspace"></span><span class="mop">sin</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop">cos</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><!----></div> <p>This follows from <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>r</mi><mo>^</mo></mover><mo>=</mo><mi>r</mi><mo stretchy="false">(</mo><mi>c</mi><mi>o</mi><mi>s</mi><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo separator="true">,</mo><mi>s</mi><mi>i</mi><mi>n</mi><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mi mathvariant="normal">/</mi><mi>r</mi></mrow><annotation encoding="application/x-tex">\hat{r} =r(cos(\theta), sin(\theta))/r</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">r</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">r</span><span class="mopen">(</span><span class="mord mathnormal">cos</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">in</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">))</span><span class="mord">/</span><span class="mord mathnormal">r</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>θ</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{\theta}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">θ</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span></span></span></span><!----></span> being orthogonal to <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>r</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{r}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">r</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span></span></span></span><!----></span> in the counter-clockwise direction. Trivially, swapping components and adding a negative sign achieves this.</p> <p>Now that we have basis vectors that are not simple, we need to take care in differentiating. For a force <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">F</mi><mo>=</mo><msub><mi>F</mi><mi>r</mi></msub><mover accent="true"><mi>r</mi><mo>^</mo></mover><mo>+</mo><msub><mi>F</mi><mi>θ</mi></msub><mover accent="true"><mi>θ</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\mathbf{F} = F_r \hat{r} + F_\theta \hat{\theta}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbf">F</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">r</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">θ</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span></span></span></span><!----></span> we want to determine what this is written as. Take a stone rotating around the origin on a string, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mi>r</mi></msub></mrow><annotation encoding="application/x-tex">F_r</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> is the tension in the string and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mi>θ</mi></msub></mrow><annotation encoding="application/x-tex">F_{\theta}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">θ</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> is any air resistant perpendiular to the string.</p> <p>To compute <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi mathvariant="bold">r</mi><mo>¨</mo></mover></mrow><annotation encoding="application/x-tex">\ddot{\mathbf{r}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathbf">r</span></span><span class="pstrut"><span class="accent-body"><span class="mord">¨</span></span></span></span></span></span></span></span></span></span><!----></span> so we can equate to <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mi>r</mi></msub><mi mathvariant="normal">/</mi><mi>m</mi></mrow><annotation encoding="application/x-tex">F_r/m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord">/</span><span class="mord mathnormal">m</span></span></span></span><!----></span>, need to differentiate:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mover accent="true"><mi mathvariant="bold">r</mi><mo>˙</mo></mover><mo>=</mo><mfrac><mrow><mi>d</mi><mi mathvariant="bold">r</mi></mrow><mrow><mi>d</mi><mi>θ</mi></mrow></mfrac><mfrac><mrow><mi>d</mi><mi>θ</mi></mrow><mrow><mi>d</mi><mi>t</mi></mrow></mfrac><mo>=</mo><mi mathvariant="bold">θ</mi><mo>⋅</mo><mover accent="true"><mi>θ</mi><mo>˙</mo></mover></mrow><annotation encoding="application/x-tex">\dot{\mathbf{r}} = \frac{d \mathbf{r}}{d \theta} \frac{d \theta}{d t} = \mathbf{\theta} \cdot \dot{\theta}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathbf">r</span></span><span class="pstrut"><span class="accent-body"><span class="mord">˙</span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">d</span><span class="mord mathnormal">θ</span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">d</span><span class="mord mathbf">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">d</span><span class="mord mathnormal">t</span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">d</span><span class="mord mathnormal">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">θ</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">θ</span></span><span class="pstrut"><span class="accent-body"><span class="mord">˙</span></span></span></span></span></span></span></span></span></span></span><!----></div> <p>Then similarly compute <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi mathvariant="bold">θ</mi><mo>˙</mo></mover><mo>=</mo><mo>−</mo><mi mathvariant="bold">r</mi><mover accent="true"><mi>θ</mi><mo>˙</mo></mover></mrow><annotation encoding="application/x-tex">\dot{\mathbf{\theta}} = - \mathbf{r} \dot{\theta}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">θ</span></span><span class="pstrut"><span class="accent-body"><span class="mord">˙</span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">−</span><span class="mord mathbf">r</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">θ</span></span><span class="pstrut"><span class="accent-body"><span class="mord">˙</span></span></span></span></span></span></span></span></span></span><!----></span>. We can differentiate again to obtain the acceleration.</p> <h4 id="example-skateboard-on-a-half-pipe"><a href="#example-skateboard-on-a-half-pipe">Example: Skateboard on a Half Pipe</a></h4> <p>Consider a Skateboard with mass <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">m</span></span></span></span><!----></span> on a half pipe of radius <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">R</span></span></span></span><!----></span>. It’s dropped from rest at an angle <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi></mrow><annotation encoding="application/x-tex">\theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">θ</span></span></span></span><!----></span> from the center of the half-pipe. As the radius is constant, we can simplify the acceleration formula by dropping out the <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>r</mi><mo>¨</mo></mover></mrow><annotation encoding="application/x-tex">\ddot{r}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">r</span></span><span class="pstrut"><span class="accent-body"><span class="mord">¨</span></span></span></span></span></span></span></span></span></span><!----></span> terms yielding <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mi>r</mi></msub><mo>=</mo><mo>−</mo><mi>m</mi><mi>R</mi><msup><mover accent="true"><mi>θ</mi><mo>˙</mo></mover><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">F_r = - m R \dot{\theta}^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">−</span><span class="mord mathnormal">m</span><span class="mord mathnormal">R</span><span class="mord"><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">θ</span></span><span class="pstrut"><span class="accent-body"><span class="mord">˙</span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mi>θ</mi></msub><mo>=</mo><mi>m</mi><mi>R</mi><mover accent="true"><mi>θ</mi><mo>¨</mo></mover></mrow><annotation encoding="application/x-tex">F_{\theta} = m R \ddot{\theta}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">θ</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">m</span><span class="mord mathnormal">R</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">θ</span></span><span class="pstrut"><span class="accent-body"><span class="mord">¨</span></span></span></span></span></span></span></span></span></span><!----></span>. The forces acting on the skateboard are <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mi>r</mi></msub><mo>=</mo><mi>m</mi><mi>g</mi><mi>cos</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>−</mo><mi>N</mi></mrow><annotation encoding="application/x-tex">F_r =mg \cos(\theta) - N</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">m</span><span class="mord mathnormal">g</span><span class="mspace"></span><span class="mop">cos</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">N</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mi>θ</mi></msub><mo>=</mo><mo>−</mo><mi>m</mi><mi>g</mi><mi>sin</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F_{\theta} = - mg \sin(\theta)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">θ</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">−</span><span class="mord mathnormal">m</span><span class="mord mathnormal">g</span><span class="mspace"></span><span class="mop">sin</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span></span></span></span><!----></span> where <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>N</mi></mrow><annotation encoding="application/x-tex">N</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">N</span></span></span></span><!----></span> is the normal force from the half-pipe. Looking at the <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi></mrow><annotation encoding="application/x-tex">\theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">θ</span></span></span></span><!----></span> equation, we have:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mover accent="true"><mi>θ</mi><mo>¨</mo></mover><mo>=</mo><mo>−</mo><mfrac><mi>g</mi><mi>R</mi></mfrac><mi>sin</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\ddot{\theta} = - \frac{g}{R} \sin(\theta)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">θ</span></span><span class="pstrut"><span class="accent-body"><span class="mord">¨</span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">−</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">R</span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">g</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace"></span><span class="mop">sin</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span></span></span></span></span><!----></div> <p>This is a nonlinear differential equation with no closed form solution. However, supposing that the skateboard is dropped near the center, we assume a small angle approximation <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>sin</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>≈</mo><mi>θ</mi></mrow><annotation encoding="application/x-tex">\sin(\theta) \approx \theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mop">sin</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">≈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">θ</span></span></span></span><!----></span>, yielding <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>θ</mi><mo>¨</mo></mover><mo>=</mo><mo>−</mo><mfrac><mi>g</mi><mi>R</mi></mfrac><mi>θ</mi></mrow><annotation encoding="application/x-tex">\ddot{\theta} = - \frac{g}{R} \theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">θ</span></span><span class="pstrut"><span class="accent-body"><span class="mord">¨</span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">−</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">R</span></span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">g</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord mathnormal">θ</span></span></span></span><!----></span>. This is a simple harmonic oscillator with solution Let <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi><mo>=</mo><msqrt><mfrac><mi>g</mi><mi>R</mi></mfrac></msqrt></mrow><annotation encoding="application/x-tex">\omega = \sqrt{\frac{g}{R}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">ω</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="svg-align"><span class="pstrut"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">R</span></span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">g</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span class="pstrut"><span class="hide-tail"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.28em" viewBox="0 0 400000 1296" preserveAspectRatio="xMinYMin slice"><path d="M263,681c0.7,0,18,39.7,52,119c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120c340,-704.7,510.7,-1060.3,512,-1067l0 -0c4.7,-7.3,11,-11,19,-11H40000v40H1012.3s-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232c-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1s-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26c-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60zM1001 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span><!----></span>, then we have:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>θ</mi><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi>θ</mi><mn>0</mn></msub><mi>cos</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>ω</mi><mi>t</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\theta(t) = \theta_0 \cos(\omega t)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">θ</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">θ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mop">cos</span><span class="mopen">(</span><span class="mord mathnormal">ω</span><span class="mord mathnormal">t</span><span class="mclose">)</span></span></span></span></span><!----></div><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="yggdrasil" scheme="https://https:///?tags=yggdrasil" />
    <category term="Lagrangian" scheme="https://https:///?tags=Lagrangian" />
    <category term="Hamiltonian" scheme="https://https:///?tags=Hamiltonian" />
    <category term="dynamics" scheme="https://https:///?tags=dynamics" />
    <category term="physics" scheme="https://https:///?tags=physics" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Distributed Training Mental Models]]></title>
    <link href="https://https:///growth/2026/distributed-training-mental-models" />
    <id>https://https:///growth/2026/distributed-training-mental-models</id>
    <published>2025-12-31T00:00:00.000Z</published>
    <updated>2025-12-31T00:00:00.000Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="overview"><a href="#overview">Overview</a></h2> <p>Build foundational mental models for distributed training. Understand the <strong>why</strong> behind DP, FSDP, ZeRO, and sharding strategies before diving into implementation.</p> <p><strong>Goal:</strong> Develop intuition for when to use which parallelism strategy and understand the memory/communication trade-offs.</p> <h2 id="key-concepts"><a href="#key-concepts">Key Concepts</a></h2> <!--[0--><div class="concept-checklist my-6 svelte-zxd1c0"><div class="flex justify-between items-center mb-4"><h3 class="text-xl font-bold flex items-center gap-2">📋 Concepts <!--[-1--><!--]--></h3> <div class="text-sm opacity-70">0 / 6 mastered</div></div> <div class="progress-bar-container mb-4"><progress class="progress progress-primary w-full" value="0" max="100">0%</progress></div> <div class="space-y-2"><!--[--><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Data Parallelism (DP) Mental Model</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Fully Sharded Data Parallel (FSDP)</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">ZeRO: Memory Optimization Stages</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Sharding Strategies &amp; Trade-offs</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Communication Patterns (AllReduce, AllGather)</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Gradient Accumulation &amp; Micro-batching</span> <!--[-1--><!--]--></label><!--]--></div> <!--[-1--><!--]--></div><!--]--><!----> <h2 id="core-mental-models"><a href="#core-mental-models">Core Mental Models</a></h2> <h3 id="1-data-parallelism-dp"><a href="#1-data-parallelism-dp">1. Data Parallelism (DP)</a></h3> <p>The simplest distributed training pattern:</p> <ul><li>Each GPU has a <strong>full copy</strong> of the model</li> <li>Data is split across GPUs</li> <li>After forward/backward, gradients are synchronized (AllReduce)</li></ul> <p><strong>When it works:</strong> Small models that fit in GPU memory.</p> <p><strong>When it breaks:</strong> Model larger than GPU memory. Enter FSDP/ZeRO.</p> <h3 id="2-fully-sharded-data-parallel-fsdp"><a href="#2-fully-sharded-data-parallel-fsdp">2. Fully Sharded Data Parallel (FSDP)</a></h3> <p>Extension of DP that shards model parameters:</p> <ul><li>Each GPU holds only a <strong>shard</strong> of the model</li> <li>Parameters are gathered (AllGather) when needed for computation</li> <li>Gradients are reduced (ReduceScatter) after backward</li></ul> <p><strong>Memory win:</strong> Model parameters divided by N GPUs.</p> <p><strong>Communication cost:</strong> More frequent AllGather/ReduceScatter operations.</p> <h3 id="3-zero-memory-optimization-stages"><a href="#3-zero-memory-optimization-stages">3. ZeRO: Memory Optimization Stages</a></h3> <p>ZeRO progressively shards different training states:</p> <ul><li><strong>ZeRO-1:</strong> Shard optimizer states only (~4├ù memory reduction)</li> <li><strong>ZeRO-2:</strong> Shard optimizer states + gradients (~8├ù reduction)</li> <li><strong>ZeRO-3:</strong> Shard optimizer states + gradients + parameters (~N├ù reduction, equivalent to FSDP)</li></ul> <p><strong>Trade-off:</strong> Higher ZeRO stages = more memory efficient, more communication overhead.</p> <h3 id="4-sharding-strategies"><a href="#4-sharding-strategies">4. Sharding Strategies</a></h3> <p><strong>Full Shard:</strong> Maximum memory savings, maximum communication (ZeRO-3/FSDP)</p> <p><strong>Hybrid Shard:</strong> Shard within nodes, replicate across nodes (balance memory &amp; communication)</p> <p><strong>No Shard:</strong> Pure data parallelism (DP)</p> <h3 id="5-communication-patterns"><a href="#5-communication-patterns">5. Communication Patterns</a></h3> <p><strong>AllReduce:</strong> Sum gradients across all GPUs (DP)</p> <p><strong>AllGather:</strong> Gather sharded parameters before forward/backward (FSDP)</p> <p><strong>ReduceScatter:</strong> Sum gradients and shard result (FSDP)</p> <p>Understanding these primitives is key to reasoning about distributed training bottlenecks.</p> <h2 id="key-resources"><a href="#key-resources">Key Resources</a></h2> <h3 id="ƒôü-essential-reading"><a href="#ƒôü-essential-reading">≡ƒôÜ Essential Reading</a></h3> <p><strong>Smol Training Playbook</strong> (HuggingFace)<br/> <a href="https://huggingface.co/spaces/HuggingFaceTB/smol-training-playbook" rel="nofollow noopener noreferrer external" target="_blank">https://huggingface.co/spaces/HuggingFaceTB/smol-training-playbook</a></p> <p>Comprehensive guide to designing model architecture, choosing parallelism strategies, and understanding distributed training trade-offs. <strong>Start here.</strong></p> <h2 id="learning-path"><a href="#learning-path">Learning Path</a></h2> <ol><li><p><strong>Conceptual Understanding (4 hours)</strong></p> <ul><li>Read Smol Training Playbook sections on parallelism</li> <li>Draw diagrams of DP vs FSDP communication patterns</li> <li>Understand when each strategy applies</li></ul></li> <li><p><strong>Mental Model Building (6 hours)</strong></p> <ul><li>Work through ZeRO stages: what gets sharded at each level?</li> <li>Calculate memory savings for a sample model (7B params)</li> <li>Map communication patterns to actual operations</li></ul></li> <li><p><strong>Hands-On Exploration (5 hours)</strong></p> <ul><li>Instrument a small model with torchrun + FSDP</li> <li>Profile memory usage at different ZeRO stages</li> <li>Measure communication overhead</li></ul></li></ol> <h2 id="common-pitfalls"><a href="#common-pitfalls">Common Pitfalls</a></h2> <p>Γ¥î <strong>“FSDP is always better”</strong> ΓÇö No! Pure DP can be faster for small models due to lower communication overhead.</p> <p>Γ¥î <strong>“ZeRO-3 = free memory”</strong> ΓÇö Communication cost increases. Understand the trade-off.</p> <p>Γ¥î <strong>“Sharding is enough”</strong> ΓÇö You also need pipeline parallelism for very large models (coming in later nodes).</p> <h2 id="next-steps"><a href="#next-steps">Next Steps</a></h2> <p>After mastering these mental models:</p> <ul><li><ul><li><strong>Fault Tolerance &amp; Suspend/Resume:</strong> How to make distributed training reliable</li></ul></li> <li><ul><li><strong>Ultra-Scale Heuristics:</strong> Practical playbook for 5D parallelism + ZeRO interplay</li></ul></li> <li><ul><li><strong>Research Harness v2:</strong> Apply these concepts to a reusable training template</li></ul></li></ul> <h2 id="assessment-criteria"><a href="#assessment-criteria">Assessment Criteria</a></h2> <p>Γ£à You understand this node when you can:</p> <ul><li>Explain when to use DP vs FSDP vs ZeRO-3 for a given model size</li> <li>Draw the communication pattern for each strategy</li> <li>Calculate memory savings from sharding</li> <li>Articulate the trade-offs (memory vs communication)</li></ul><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="yggdrasil" scheme="https://https:///?tags=yggdrasil" />
    <category term="systems-hpc" scheme="https://https:///?tags=systems-hpc" />
    <category term="distributed" scheme="https://https:///?tags=distributed" />
    <category term="DP" scheme="https://https:///?tags=DP" />
    <category term="FSDP" scheme="https://https:///?tags=FSDP" />
    <category term="ZeRO" scheme="https://https:///?tags=ZeRO" />
    <category term="sharding" scheme="https://https:///?tags=sharding" />
    <category term="mental-models" scheme="https://https:///?tags=mental-models" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Flow Matching Fundamentals]]></title>
    <link href="https://https:///growth/2026/flow-matching-fundamentals" />
    <id>https://https:///growth/2026/flow-matching-fundamentals</id>
    <published>2025-12-31T00:00:00.000Z</published>
    <updated>2025-12-31T00:00:00.000Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="overview"><a href="#overview">Overview</a></h2> <p>Master the conceptual foundation of flow matching and continuous normalizing flows. Understand how to learn a trajectory from noise to data by training a vector field.</p> <p><strong>Goal:</strong> Build intuition for the ODE perspective on generative modeling and understand why flow matching is often simpler than diffusion.</p> <h2 id="key-concepts"><a href="#key-concepts">Key Concepts</a></h2> <!--[0--><div class="concept-checklist my-6 svelte-zxd1c0"><div class="flex justify-between items-center mb-4"><h3 class="text-xl font-bold flex items-center gap-2">📋 Concepts <!--[-1--><!--]--></h3> <div class="text-sm opacity-70">0 / 5 mastered</div></div> <div class="progress-bar-container mb-4"><progress class="progress progress-primary w-full" value="0" max="100">0%</progress></div> <div class="space-y-2"><!--[--><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">ODE Trajectory Mental Model</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Flow Matching Objective: Conditional &amp; Marginal</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Flow Matching vs Diffusion Models</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">ODE Solvers for Sampling (Euler, RK4, DPM-Solver)</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Training: Regression on Vector Fields</span> <!--[-1--><!--]--></label><!--]--></div> <!--[-1--><!--]--></div><!--]--><!----> <h2 id="the-ode-trajectory-mental-model"><a href="#the-ode-trajectory-mental-model">The ODE Trajectory Mental Model</a></h2> <p><strong>Core idea:</strong> Generative modeling as learning a <strong>continuous path</strong> from noise <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>z</mi><mn>0</mn></msub><mo>∼</mo><mi mathvariant="script">N</mi><mo stretchy="false">(</mo><mn>0</mn><mo separator="true">,</mo><mi>I</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">z_0 \sim \mathcal{N}(0, I)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">∼</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathcal">N</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">I</span><span class="mclose">)</span></span></span></span><!----></span> to data <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>z</mi><mn>1</mn></msub><mo>∼</mo><msub><mi>p</mi><mtext>data</mtext></msub></mrow><annotation encoding="application/x-tex">z_1 \sim p_{\text{data}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">∼</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">data</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>.</p> <p>Define an ODE:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mfrac><mrow><mi>d</mi><msub><mi>z</mi><mi>t</mi></msub></mrow><mrow><mi>d</mi><mi>t</mi></mrow></mfrac><mo>=</mo><msub><mi>v</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><msub><mi>z</mi><mi>t</mi></msub><mo separator="true">,</mo><mi>t</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\frac{dz_t}{dt} = v_\theta(z_t, t)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">d</span><span class="mord mathnormal">t</span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">d</span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">t</span><span class="mclose">)</span></span></span></span></span><!----></div> <p>Where <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mi>θ</mi></msub></mrow><annotation encoding="application/x-tex">v_\theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> is a learned <strong>vector field</strong>.</p> <p><strong>Forward process:</strong> <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>z</mi><mn>0</mn></msub><mo>→</mo><msub><mi>z</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">z_0 \to z_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">→</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> (noise to data)<br/> <strong>Sampling:</strong> Solve ODE forward from <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>z</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">z_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> to get <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>z</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">z_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span></p> <p><strong>Intuition:</strong> Instead of learning to denoise (diffusion), learn the <strong>velocity</strong> at each point along the path.</p> <h2 id="flow-matching-objective"><a href="#flow-matching-objective">Flow Matching Objective</a></h2> <p><strong>Goal:</strong> Train <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mi>θ</mi></msub></mrow><annotation encoding="application/x-tex">v_\theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> to match the true vector field <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mi>t</mi></msub></mrow><annotation encoding="application/x-tex">v_t</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>.</p> <p><strong>Conditional flow matching loss:</strong></p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="script">L</mi><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi mathvariant="double-struck">E</mi><mrow><mi>t</mi><mo separator="true">,</mo><msub><mi>z</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>z</mi><mi>t</mi></msub></mrow></msub><mrow><mo fence="true">[</mo><mi mathvariant="normal">∥</mi><msub><mi>v</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><msub><mi>z</mi><mi>t</mi></msub><mo separator="true">,</mo><mi>t</mi><mo stretchy="false">)</mo><mo>−</mo><msub><mi>u</mi><mi>t</mi></msub><mo stretchy="false">(</mo><msub><mi>z</mi><mi>t</mi></msub><mi mathvariant="normal">∣</mi><msub><mi>z</mi><mn>1</mn></msub><mo stretchy="false">)</mo><msup><mi mathvariant="normal">∥</mi><mn>2</mn></msup><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">\mathcal{L}(\theta) = \mathbb{E}_{t, z_1, z_t} \left[ \| v_\theta(z_t, t) - u_t(z_t | z_1) \|^2 \right]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathcal">L</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathbb">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size1">[</span></span><span class="mord">∥</span><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mord"><span class="mord">∥</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose delimcenter"><span class="delimsizing size1">]</span></span></span></span></span></span></span><!----></div> <p>Where:</p> <ul><li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>z</mi><mn>1</mn></msub><mo>∼</mo><msub><mi>p</mi><mtext>data</mtext></msub></mrow><annotation encoding="application/x-tex">z_1 \sim p_{\text{data}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">∼</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">data</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>: Real data sample</li> <li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>z</mi><mi>t</mi></msub><mo>=</mo><msub><mi>α</mi><mi>t</mi></msub><msub><mi>z</mi><mn>1</mn></msub><mo>+</mo><msub><mi>σ</mi><mi>t</mi></msub><mi>ϵ</mi></mrow><annotation encoding="application/x-tex">z_t = \alpha_t z_1 + \sigma_t \epsilon</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord mathnormal">ϵ</span></span></span></span><!----></span>: Interpolated sample at time <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>t</mi></mrow><annotation encoding="application/x-tex">t</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">t</span></span></span></span><!----></span></li> <li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>u</mi><mi>t</mi></msub><mo stretchy="false">(</mo><msub><mi>z</mi><mi>t</mi></msub><mi mathvariant="normal">∣</mi><msub><mi>z</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">u_t(z_t | z_1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span>: Target vector field (analytically computable!)</li></ul> <p><strong>Key insight:</strong> Unlike diffusion (which requires score matching), flow matching has a <strong>simple regression objective</strong>.</p> <h2 id="flow-matching-vs-diffusion-models"><a href="#flow-matching-vs-diffusion-models">Flow Matching vs Diffusion Models</a></h2> <div class="prose-table-wrap overflow-x-auto mb-4 svelte-521o0"><table class="table svelte-521o0"><thead><tr><th>Aspect</th><th>Diffusion Models</th><th>Flow Matching</th></tr></thead> <tbody><tr><td><strong>Forward process</strong></td><td>Stochastic (SDE)</td><td>Deterministic (ODE)</td></tr><tr><td><strong>Training objective</strong></td><td>Score matching (Γêç log p)</td><td>Vector field regression</td></tr><tr><td><strong>Sampling</strong></td><td>SDE/ODE solvers</td><td>ODE solvers only</td></tr><tr><td><strong>Simplicity</strong></td><td>More complex</td><td>Simpler math</td></tr><tr><td><strong>Flexibility</strong></td><td>Fixed noise schedule</td><td>Flexible paths</td></tr></tbody><!----></table></div><!----> <p><strong>When to use flow matching:</strong></p> <ul><li>You want a simpler training objective</li> <li>You want to design custom interpolation paths</li> <li>You prefer deterministic generation</li></ul> <p><strong>When to use diffusion:</strong></p> <ul><li>You want stochasticity for diversity</li> <li>You’re using existing diffusion codebases (Stable Diffusion, etc.)</li></ul> <h2 id="ode-solvers-for-sampling"><a href="#ode-solvers-for-sampling">ODE Solvers for Sampling</a></h2> <p><strong>Euler method</strong> (simplest):</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>z</mi><mrow><mi>t</mi><mo>+</mo><mi mathvariant="normal">Δ</mi><mi>t</mi></mrow></msub><mo>=</mo><msub><mi>z</mi><mi>t</mi></msub><mo>+</mo><mi mathvariant="normal">Δ</mi><mi>t</mi><mo>⋅</mo><msub><mi>v</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><msub><mi>z</mi><mi>t</mi></msub><mo separator="true">,</mo><mi>t</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">z_{t+\Delta t} = z_t + \Delta t \cdot v_\theta(z_t, t)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mbin mtight">+</span><span class="mord mtight">Δ</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">Δ</span><span class="mord mathnormal">t</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">t</span><span class="mclose">)</span></span></span></span></span><!----></div> <p><strong>Runge-Kutta 4 (RK4)</strong> (more accurate, fewer steps):More complex multi-stage method, but allows larger <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Δ</mi><mi>t</mi></mrow><annotation encoding="application/x-tex">\Delta t</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">Δ</span><span class="mord mathnormal">t</span></span></span></span><!----></span>.</p> <p><strong>DPM-Solver</strong> (optimized for generative models):Exploits structure of learned vector fields for fast sampling.</p> <p><strong>Trade-off:</strong> Accuracy vs speed. Euler needs ~100 steps, RK4 ~50 steps, DPM-Solver ~20 steps.</p> <h2 id="training-flow-matching-models"><a href="#training-flow-matching-models">Training Flow Matching Models</a></h2> <h3 id="algorithm"><a href="#algorithm">Algorithm</a></h3> <ol><li>Sample data <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>z</mi><mn>1</mn></msub><mo>∼</mo><msub><mi>p</mi><mtext>data</mtext></msub></mrow><annotation encoding="application/x-tex">z_1 \sim p_{\text{data}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">∼</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">data</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span></li> <li>Sample noise <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ϵ</mi><mo>∼</mo><mi mathvariant="script">N</mi><mo stretchy="false">(</mo><mn>0</mn><mo separator="true">,</mo><mi>I</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\epsilon \sim \mathcal{N}(0, I)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">ϵ</span><span class="mspace"></span><span class="mrel">∼</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathcal">N</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">I</span><span class="mclose">)</span></span></span></span><!----></span></li> <li>Sample time <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>t</mi><mo>∼</mo><mi>U</mi><mo stretchy="false">(</mo><mn>0</mn><mo separator="true">,</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">t \sim U(0, 1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">t</span><span class="mspace"></span><span class="mrel">∼</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">U</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><!----></span></li> <li>Interpolate: <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>z</mi><mi>t</mi></msub><mo>=</mo><msub><mi>α</mi><mi>t</mi></msub><msub><mi>z</mi><mn>1</mn></msub><mo>+</mo><msub><mi>σ</mi><mi>t</mi></msub><mi>ϵ</mi></mrow><annotation encoding="application/x-tex">z_t = \alpha_t z_1 + \sigma_t \epsilon</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord mathnormal">ϵ</span></span></span></span><!----></span></li> <li>Compute target: <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>u</mi><mi>t</mi></msub><mo>=</mo><mfrac><mi>d</mi><mrow><mi>d</mi><mi>t</mi></mrow></mfrac><mo stretchy="false">(</mo><msub><mi>α</mi><mi>t</mi></msub><msub><mi>z</mi><mn>1</mn></msub><mo>+</mo><msub><mi>σ</mi><mi>t</mi></msub><mi>ϵ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">u_t = \frac{d}{dt}(\alpha_t z_1 + \sigma_t \epsilon)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">t</span></span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord mathnormal">ϵ</span><span class="mclose">)</span></span></span></span><!----></span></li> <li>Loss: <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∥</mi><msub><mi>v</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><msub><mi>z</mi><mi>t</mi></msub><mo separator="true">,</mo><mi>t</mi><mo stretchy="false">)</mo><mo>−</mo><msub><mi>u</mi><mi>t</mi></msub><msup><mi mathvariant="normal">∥</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">\| v_\theta(z_t, t) - u_t \|^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∥</span><span class="mord"><span class="mord mathnormal">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord"><span class="mord">∥</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><!----></span></li></ol> <p><strong>Key:</strong> The target <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>u</mi><mi>t</mi></msub></mrow><annotation encoding="application/x-tex">u_t</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> is analytically known (no score estimation needed).</p> <h3 id="interpolation-schedule"><a href="#interpolation-schedule">Interpolation Schedule</a></h3> <p><strong>Linear interpolation:</strong></p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>z</mi><mi>t</mi></msub><mo>=</mo><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mi>t</mi><mo stretchy="false">)</mo><msub><mi>z</mi><mn>0</mn></msub><mo>+</mo><mi>t</mi><msub><mi>z</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">z_t = (1-t) z_0 + t z_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">t</span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><!----></div> <p><strong>Variance-preserving (VP):</strong></p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>z</mi><mi>t</mi></msub><mo>=</mo><msqrt><mrow><mn>1</mn><mo>−</mo><msubsup><mi>σ</mi><mi>t</mi><mn>2</mn></msubsup></mrow></msqrt><msub><mi>z</mi><mn>1</mn></msub><mo>+</mo><msub><mi>σ</mi><mi>t</mi></msub><mi>ϵ</mi></mrow><annotation encoding="application/x-tex">z_t = \sqrt{1-\sigma_t^2} z_1 + \sigma_t \epsilon</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="svg-align"><span class="pstrut"></span><span class="mord"><span class="mord">1</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span><span class="pstrut"><span class="hide-tail"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.88em" viewBox="0 0 400000 1944" preserveAspectRatio="xMinYMin slice"><path d="M983 90l0 -0c4,-6.7,10,-10,18,-10 H400000v40H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7s-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744c-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30c26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722c56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5c53.7,-170.3,84.5,-266.8,92.5,-289.5zM1001 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mord"><span class="mord mathnormal">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord mathnormal">ϵ</span></span></span></span></span><!----></div> <p><strong>Choice matters:</strong> Affects sample quality and training stability.</p> <h2 id="key-resources"><a href="#key-resources">Key Resources</a></h2> <h3 id="ƒôü-essential-reading"><a href="#ƒôü-essential-reading">≡ƒôÜ Essential Reading</a></h3> <p><strong>Flow Matching for Generative Modeling</strong> (arXiv:2510.21890)<br/> <a href="https://www.arxiv.org/abs/2510.21890" rel="nofollow noopener noreferrer external" target="_blank">https://www.arxiv.org/abs/2510.21890</a></p> <p>Comprehensive tutorial on flow matching for diffusion modeling. Explains the connection between diffusion and flows, and why flow matching often leads to simpler training. <strong>Start here.</strong></p> <p><strong>MIT Diffusion Course 2025</strong><br/> <a href="https://diffusion.csail.mit.edu/2025/" rel="nofollow noopener noreferrer external" target="_blank">https://diffusion.csail.mit.edu/2025/</a></p> <p>MIT course covering diffusion models and flow matching with lectures, notes, and code. <strong>Excellent for structured learning.</strong></p> <h2 id="learning-path"><a href="#learning-path">Learning Path</a></h2> <h3 id="phase-1-theory-5-hours"><a href="#phase-1-theory-5-hours">Phase 1: Theory (5 hours)</a></h3> <ol><li>Read flow matching arXiv paper (2510.21890)</li> <li>Work through ODE trajectory derivations</li> <li>Compare to diffusion formulation</li></ol> <h3 id="phase-2-implementation-5-hours"><a href="#phase-2-implementation-5-hours">Phase 2: Implementation (5 hours)</a></h3> <ol><li>Implement flow matching on 2D toy data (moons, circles)</li> <li>Visualize learned vector fields</li> <li>Experiment with different interpolation schedules</li> <li>Compare Euler vs RK4 sampling</li></ol> <h3 id="phase-3-deep-dive-2-hours"><a href="#phase-3-deep-dive-2-hours">Phase 3: Deep Dive (2 hours)</a></h3> <ol><li>Watch MIT Diffusion Course lectures on flow matching</li> <li>Read original Conditional Flow Matching paper (Lipman et al.)</li> <li>Understand Rectified Flow (next node prerequisite)</li></ol> <h2 id="common-pitfalls"><a href="#common-pitfalls">Common Pitfalls</a></h2> <p>Γ¥î <strong>Confusing forward/backward:</strong> Sampling goes <strong>forward</strong> in time (0to1), not backward like diffusion.</p> <p>Γ¥î <strong>Wrong target vector:</strong> Make sure to use the conditional target (u_t(z_t | z_1)), not the marginal.</p> <p>Γ¥î <strong>Too few sampling steps:</strong> Euler method needs ~100 steps. Use adaptive solvers for faster sampling.</p> <p>Γ¥î <strong>Ignoring interpolation schedule:</strong> Linear interpolation works but VP schedules often train faster.</p> <h2 id="next-steps"><a href="#next-steps">Next Steps</a></h2> <ul><li>to <strong>Rectified Flow / Consistency Toolkit:</strong> Modern training and distillation methods</li> <li>to <strong>Conditioning &amp; Control:</strong> Add T2V, I2V, camera control to flow models</li></ul> <h2 id="assessment-criteria"><a href="#assessment-criteria">Assessment Criteria</a></h2> <p>Γ£à You understand this node when you can:</p> <ul><li>Explain the ODE trajectory view of generative modeling</li> <li>Derive the flow matching loss from scratch</li> <li>Implement flow matching on toy datasets</li> <li>Articulate the difference from diffusion models</li> <li>Choose appropriate ODE solvers for sampling</li></ul><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="yggdrasil" scheme="https://https:///?tags=yggdrasil" />
    <category term="gen-media" scheme="https://https:///?tags=gen-media" />
    <category term="ODE" scheme="https://https:///?tags=ODE" />
    <category term="flow-matching" scheme="https://https:///?tags=flow-matching" />
    <category term="trajectory" scheme="https://https:///?tags=trajectory" />
    <category term="diffusion" scheme="https://https:///?tags=diffusion" />
    <category term="continuous-normalizing-flows" scheme="https://https:///?tags=continuous-normalizing-flows" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Functional Programming]]></title>
    <link href="https://https:///growth/2026/functional-programming" />
    <id>https://https:///growth/2026/functional-programming</id>
    <published>2025-12-31T00:00:00.000Z</published>
    <updated>2025-12-31T00:00:00.000Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="overview"><a href="#overview">Overview</a></h2> <p>Brief introduction to Functional Programming.</p> <h2 id="key-concepts"><a href="#key-concepts">Key Concepts</a></h2> <!--[0--><div class="concept-checklist my-6 svelte-zxd1c0"><div class="flex justify-between items-center mb-4"><h3 class="text-xl font-bold flex items-center gap-2">📋 Concepts <!--[-1--><!--]--></h3> <div class="text-sm opacity-70">0 / 2 mastered</div></div> <div class="progress-bar-container mb-4"><progress class="progress progress-primary w-full" value="0" max="100">0%</progress></div> <div class="space-y-2"><!--[--><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Core Concept 1</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Core Concept 2</span> <!--[-1--><!--]--></label><!--]--></div> <!--[-1--><!--]--></div><!--]--><!----> <h2 id="learning-path"><a href="#learning-path">Learning Path</a></h2> <h3 id="concept-1"><a href="#concept-1">Concept 1</a></h3> <p>Content here…</p> <h3 id="concept-2"><a href="#concept-2">Concept 2</a></h3> <p>Content here…</p> <h2 id="implementation"><a href="#implementation">Implementation</a></h2> <p>Practical examples and code…</p> <h2 id="resources"><a href="#resources">Resources</a></h2> <ul><li>Resource 1</li> <li>Resource 2</li></ul> <h2 id="next-steps"><a href="#next-steps">Next Steps</a></h2> <p>What to learn after completing this node.</p><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="yggdrasil" scheme="https://https:///?tags=yggdrasil" />
    <category term="swe" scheme="https://https:///?tags=swe" />
    <category term="fp" scheme="https://https:///?tags=fp" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Online Loops & Stability]]></title>
    <link href="https://https:///growth/2026/online-loops-stability" />
    <id>https://https:///growth/2026/online-loops-stability</id>
    <published>2025-12-31T00:00:00.000Z</published>
    <updated>2025-12-31T00:00:00.000Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="overview"><a href="#overview">Overview</a></h2> <p>Master the art of iterative online RL training. Understand distribution shift, reward hacking, and the stability knobs needed to keep training on track when both policy and reward model evolve.</p> <p><strong>Goal:</strong> Build robust online RL systems that don’t collapse or hack rewards.</p> <h2 id="key-concepts"><a href="#key-concepts">Key Concepts</a></h2> <!--[0--><div class="concept-checklist my-6 svelte-zxd1c0"><div class="flex justify-between items-center mb-4"><h3 class="text-xl font-bold flex items-center gap-2">📋 Concepts <!--[-1--><!--]--></h3> <div class="text-sm opacity-70">0 / 7 mastered</div></div> <div class="progress-bar-container mb-4"><progress class="progress progress-primary w-full" value="0" max="100">0%</progress></div> <div class="space-y-2"><!--[--><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Online RL: Data Collection + Training Loop</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Distribution Shift: Policy vs Reward Model</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Reward Hacking: Detection &amp; Mitigation</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">KL Regularization: Reference Policy Anchoring</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Reward Model Updates: When &amp; How</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Stability Knobs: LR schedules, KL budgets, RM freezing</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">LLM Learning Dynamics: SFT - PPO - DPO</span> <!--[-1--><!--]--></label><!--]--></div> <!--[-1--><!--]--></div><!--]--><!----> <h2 id="online-rl-loop"><a href="#online-rl-loop">Online RL Loop</a></h2> <p><strong>Classic RL:</strong> Fixed environment, train policy.</p> <p><strong>RLHF/Online RL:</strong> Environment (reward model) and policy both evolve.</p> <p><strong>Loop:</strong></p> <ol><li>Collect data with current policy <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mi>θ</mi></msub></mrow><annotation encoding="application/x-tex">\pi_\theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span></li> <li>Train reward model <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>r</mi><mi>ϕ</mi></msub></mrow><annotation encoding="application/x-tex">r_\phi</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">ϕ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> on new preferences</li> <li>Run PPO to optimize <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mi>θ</mi></msub></mrow><annotation encoding="application/x-tex">\pi_\theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> against <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>r</mi><mi>ϕ</mi></msub></mrow><annotation encoding="application/x-tex">r_\phi</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">ϕ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span></li> <li>Repeat</li></ol> <p><strong>Challenge:</strong> How to keep this stable when both <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>π</mi></mrow><annotation encoding="application/x-tex">\pi</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">π</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>r</mi></mrow><annotation encoding="application/x-tex">r</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">r</span></span></span></span><!----></span> are moving targets?</p> <h2 id="distribution-shift"><a href="#distribution-shift">Distribution Shift</a></h2> <p><strong>Problem:</strong> Reward model trained on data from <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mtext>old</mtext></msub></mrow><annotation encoding="application/x-tex">\pi_{\text{old}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">old</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>, but we’re using it to evaluate <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mtext>new</mtext></msub></mrow><annotation encoding="application/x-tex">\pi_{\text{new}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">new</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>.</p> <p><strong>Consequence:</strong> Reward model becomes <strong>miscalibrated</strong> on new policy outputs.</p> <p><strong>Symptoms:</strong></p> <ul><li>Reward scores inflate without quality improvement</li> <li>Policy generates adversarial examples that fool RM</li> <li>Human raters disagree with RM scores</li></ul> <p><strong>Solutions:</strong></p> <ol><li><strong>KL regularization:</strong> Keep policy close to reference <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mtext>ref</mtext></msub></mrow><annotation encoding="application/x-tex">\pi_{\text{ref}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">ref</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span></li> <li><strong>Iterative RM updates:</strong> Collect new preferences on <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mtext>new</mtext></msub></mrow><annotation encoding="application/x-tex">\pi_{\text{new}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">new</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> outputs</li> <li><strong>Ensemble RMs:</strong> Use multiple RMs to detect disagreement</li></ol> <h2 id="reward-hacking"><a href="#reward-hacking">Reward Hacking</a></h2> <p><strong>Definition:</strong> Policy learns to exploit flaws in the reward model without improving actual quality.</p> <p><strong>Examples:</strong></p> <ul><li>Generating verbose but low-content responses (RM prefers length)</li> <li>Using rare tokens RM hasn’t seen (RM assigns high uncertainty - high reward)</li> <li>Repeating patterns RM can’t detect (e.g., subtle repetition)</li></ul> <p><strong>Detection:</strong></p> <ol><li><strong>Human eval diverges from RM:</strong> RM says great, humans say bad</li> <li><strong>RM ensemble disagrees:</strong> RMs give wildly different scores</li> <li><strong>KL explodes:</strong> Policy strays far from reference</li></ol> <p><strong>Mitigation:</strong></p> <ol><li><strong>KL penalty:</strong> <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext>reward</mtext><mo>=</mo><msub><mi>r</mi><mi>ϕ</mi></msub><mo stretchy="false">(</mo><mtext>output</mtext><mo stretchy="false">)</mo><mo>−</mo><mi>β</mi><mo>⋅</mo><mtext>KL</mtext><mo stretchy="false">(</mo><mi>π</mi><mi mathvariant="normal">∣</mi><mi mathvariant="normal">∣</mi><msub><mi>π</mi><mtext>ref</mtext></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\text{reward} = r_\phi(\text{output}) - \beta \cdot \text{KL}(\pi || \pi_{\text{ref}})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord text"><span class="mord">reward</span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">ϕ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord text"><span class="mord">output</span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">β</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord text"><span class="mord">KL</span></span><span class="mopen">(</span><span class="mord mathnormal">π</span><span class="mord">∣∣</span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">ref</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span></li> <li><strong>RM ensemble:</strong> Only trust reward if all RMs agree</li> <li><strong>Human-in-the-loop:</strong> Regular human audits</li> <li><strong>Adversarial RM training:</strong> Collect hacked examples, retrain RM</li></ol> <h2 id="kl-regularization"><a href="#kl-regularization">KL Regularization</a></h2> <p><strong>Objective:</strong></p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><munder><mrow><mi>max</mi><mo>⁡</mo></mrow><mi>θ</mi></munder><msub><mi mathvariant="double-struck">E</mi><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∼</mo><msub><mi>π</mi><mi>θ</mi></msub></mrow></msub><mrow><mo fence="true">[</mo><msub><mi>r</mi><mi>ϕ</mi></msub><mo stretchy="false">(</mo><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo stretchy="false">)</mo><mo>−</mo><mi>β</mi><mo>⋅</mo><mtext>KL</mtext><mo stretchy="false">(</mo><msub><mi>π</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><mi>y</mi><mi mathvariant="normal">∣</mi><mi>x</mi><mo stretchy="false">)</mo><mi mathvariant="normal">∣</mi><mi mathvariant="normal">∣</mi><msub><mi>π</mi><mtext>ref</mtext></msub><mo stretchy="false">(</mo><mi>y</mi><mi mathvariant="normal">∣</mi><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">\max_\theta \mathbb{E}_{x, y \sim \pi_\theta} \left[ r_\phi(x, y) - \beta \cdot \text{KL}(\pi_\theta(y|x) || \pi_{\text{ref}}(y|x)) \right]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span><span class="pstrut"><span class="mop">max</span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="mord"><span class="mord mathbb">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">y</span><span class="mrel mtight">∼</span><span class="mord mtight"><span class="mord mathnormal mtight">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter">[</span><span class="mord"><span class="mord mathnormal">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">ϕ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">y</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord mathnormal">β</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span><span class="mord text"><span class="mord">KL</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">y</span><span class="mord">∣</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mord">∣∣</span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">ref</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">y</span><span class="mord">∣</span><span class="mord mathnormal">x</span><span class="mclose">))</span><span class="mclose delimcenter">]</span></span></span></span></span></span><!----></div> <p><strong>Intuition:</strong> Optimize reward but don’t stray too far from reference policy.</p> <p><strong>Tuning <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi></mrow><annotation encoding="application/x-tex">\beta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">β</span></span></span></span><!----></span>:</strong></p> <ul><li>Too small - reward hacking</li> <li>Too large - policy doesn’t improve</li> <li>Typical range: 0.01ΓÇô0.1 (tune empirically)</li></ul> <p><strong>Adaptive KL:</strong> Use KL budget that adjusts based on training progress.</p> <h2 id="reward-model-updates"><a href="#reward-model-updates">Reward Model Updates</a></h2> <p><strong>When to update RM:</strong></p> <ul><li>Γ£à After every N iterations (e.g., every 5 PPO rounds)</li> <li>Γ£à When KL divergence crosses threshold (policy drifted too far)</li> <li>Γ£à When human eval shows RM miscalibration</li></ul> <p><strong>How to update RM:</strong></p> <ol><li>Collect new preference data from current policy outputs</li> <li>Finetune RM (don’t reset!) on mixed dataset (old + new)</li> <li>Validate RM on held-out preferences</li> <li>If RM quality degrades, rollback or use ensemble</li></ol> <p><strong>Risk:</strong> RM overfitting to current policy - amplifies hacking.</p> <p><strong>Solution:</strong> Keep diverse preference dataset spanning many policy checkpoints.</p> <h2 id="stability-knobs"><a href="#stability-knobs">Stability Knobs</a></h2> <h3 id="learning-rate-schedules"><a href="#learning-rate-schedules">Learning Rate Schedules</a></h3> <ul><li>Start with high LR for fast initial progress</li> <li>Decay LR as policy stabilizes</li> <li>Use warmup for RM updates</li></ul> <h3 id="kl-budget-management"><a href="#kl-budget-management">KL Budget Management</a></h3> <ul><li>Start with low KL budget (conservative)</li> <li>Gradually increase as RM gets more data</li> <li>Monitor KL per-iteration, not just cumulative</li></ul> <h3 id="rm-freezing-periods"><a href="#rm-freezing-periods">RM Freezing Periods</a></h3> <ul><li>Freeze RM for N iterations to let policy catch up</li> <li>Update RM only when policy plateaus</li></ul> <h3 id="checkpointing--rollback"><a href="#checkpointing--rollback">Checkpointing &amp; Rollback</a></h3> <ul><li>Save policy checkpoints every iteration</li> <li>If reward hacking detected, rollback to last good checkpoint</li></ul> <h2 id="llm-learning-dynamics"><a href="#llm-learning-dynamics">LLM Learning Dynamics</a></h2> <p><strong>SFT - PPO - DPO progression:</strong></p> <ol><li><strong>SFT (Supervised Fine-Tuning):</strong> Learn from demonstrations <ul><li>Fast initial progress</li> <li>Upper bounded by demo quality</li></ul></li> <li><strong>PPO (Online RL):</strong> Optimize reward model <ul><li>Can surpass demos</li> <li>Requires careful tuning</li></ul></li> <li><strong>DPO (Direct Preference Optimization):</strong> Offline preference learning <ul><li>Simpler, no reward model</li> <li>Less prone to hacking</li></ul></li></ol> <p><strong>Key insight:</strong> Different algorithms shine at different stages of training.</p> <h2 id="key-resources"><a href="#key-resources">Key Resources</a></h2> <h3 id="ƒôü-essential-papers"><a href="#ƒôü-essential-papers">≡ƒôÜ Essential Papers</a></h3> <p><strong>Understanding LLM Learning Dynamics</strong> (arXiv:2407.10490)<br/> <a href="https://arxiv.org/abs/2407.10490" rel="nofollow noopener noreferrer external" target="_blank">https://arxiv.org/abs/2407.10490</a></p> <p>Deep analysis of SFT, PPO, and DPO learning dynamics for LLMs. Essential for understanding when each algorithm works best and how they interact. <strong>Must-read for RLHF practitioners.</strong></p> <p><strong>The RLHF Book</strong><br/> <a href="https://rlhfbook.com/" rel="nofollow noopener noreferrer external" target="_blank">https://rlhfbook.com/</a></p> <p>Chapters on online training, distribution shift, and reward hacking with practical advice.</p> <h2 id="learning-path"><a href="#learning-path">Learning Path</a></h2> <h3 id="phase-1-understand-the-dynamics-6-hours"><a href="#phase-1-understand-the-dynamics-6-hours">Phase 1: Understand the Dynamics (6 hours)</a></h3> <ol><li>Read arXiv:2407.10490 (LLM learning dynamics)</li> <li>Study RLHF Book chapters on online loops</li> <li>Understand failure modes (reward hacking, distribution shift)</li></ol> <h3 id="phase-2-implement-10-hours"><a href="#phase-2-implement-10-hours">Phase 2: Implement (10 hours)</a></h3> <ol><li>Build online RL loop: PPO + iterative RM updates</li> <li>Implement KL regularization with tunable (\beta)</li> <li>Add monitoring: KL divergence, RM calibration, human eval</li> <li>Simulate reward hacking and test mitigation strategies</li></ol> <h3 id="phase-3-stability-engineering-4-hours"><a href="#phase-3-stability-engineering-4-hours">Phase 3: Stability Engineering (4 hours)</a></h3> <ol><li>Experiment with different RM update frequencies</li> <li>Tune KL budget over training</li> <li>Implement RM ensemble for hacking detection</li> <li>Build rollback system for catastrophic failures</li></ol> <h2 id="common-pitfalls"><a href="#common-pitfalls">Common Pitfalls</a></h2> <p>Γ¥î <strong>Never updating RM:</strong> Policy will eventually hack a fixed RM.</p> <p>Γ¥î <strong>Updating RM too often:</strong> RM overfits to current policy.</p> <p>Γ¥î <strong>No KL regularization:</strong> Guaranteed reward hacking.</p> <p>Γ¥î <strong>Ignoring human eval:</strong> RM scores become meaningless without ground truth.</p> <p>Γ¥î <strong>No rollback plan:</strong> When training goes off the rails, you’re stuck.</p> <h2 id="next-steps"><a href="#next-steps">Next Steps</a></h2> <ul><li><ul><li><strong>Search / Test-Time Compute:</strong> Use RMs at inference time for best-of-N sampling</li></ul></li> <li><ul><li><strong>RL for Structured Outputs:</strong> Apply online RL to constrained generation (layouts, CDFs)</li></ul></li></ul> <h2 id="assessment-criteria"><a href="#assessment-criteria">Assessment Criteria</a></h2> <p>Γ£à You understand this node when you can:</p> <ul><li>Implement a full online RL loop with iterative RM updates</li> <li>Detect and mitigate reward hacking</li> <li>Tune KL regularization based on training dynamics</li> <li>Monitor distribution shift and RM calibration</li> <li>Explain SFT - PPO - DPO progression</li> <li>Build robust checkpointing and rollback systems</li></ul><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="yggdrasil" scheme="https://https:///?tags=yggdrasil" />
    <category term="rl" scheme="https://https:///?tags=rl" />
    <category term="online" scheme="https://https:///?tags=online" />
    <category term="distribution-shift" scheme="https://https:///?tags=distribution-shift" />
    <category term="stability" scheme="https://https:///?tags=stability" />
    <category term="iterative-training" scheme="https://https:///?tags=iterative-training" />
    <category term="RL" scheme="https://https:///?tags=RL" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Policy Gradient Core]]></title>
    <link href="https://https:///growth/2026/policy-gradient-core" />
    <id>https://https:///growth/2026/policy-gradient-core</id>
    <published>2025-12-31T00:00:00.000Z</published>
    <updated>2025-12-31T00:00:00.000Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="overview"><a href="#overview">Overview</a></h2> <p>Build the foundational understanding of policy gradient methods from first principles. Derive the policy gradient theorem, implement REINFORCE, and understand the actor-critic paradigm.</p> <p><strong>Goal:</strong> Deeply understand <strong>why</strong> we can optimize policies directly by maximizing expected reward.</p> <h2 id="key-concepts"><a href="#key-concepts">Key Concepts</a></h2> <!--[0--><div class="concept-checklist my-6 svelte-zxd1c0"><div class="flex justify-between items-center mb-4"><h3 class="text-xl font-bold flex items-center gap-2">📋 Concepts <!--[-1--><!--]--></h3> <div class="text-sm opacity-70">0 / 5 mastered</div></div> <div class="progress-bar-container mb-4"><progress class="progress progress-primary w-full" value="0" max="100">0%</progress></div> <div class="space-y-2"><!--[--><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Policy Gradient Theorem: Derivation</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">REINFORCE Algorithm: Monte Carlo PG</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Variance Reduction: Baselines</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Actor-Critic Architecture</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Advantage Estimation (GAE)</span> <!--[-1--><!--]--></label><!--]--></div> <!--[-1--><!--]--></div><!--]--><!----> <h2 id="the-policy-gradient-theorem"><a href="#the-policy-gradient-theorem">The Policy Gradient Theorem</a></h2> <p><strong>Core idea:</strong> Instead of learning Q-values (value-based RL), directly parameterize and optimize the policy <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><mi>a</mi><mi mathvariant="normal">∣</mi><mi>s</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\pi_\theta(a|s)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">s</span><span class="mclose">)</span></span></span></span><!----></span>.</p> <p><strong>Policy Gradient Theorem:</strong></p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi mathvariant="normal">∇</mi><mi>θ</mi></msub><mi>J</mi><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi mathvariant="double-struck">E</mi><mrow><mi>τ</mi><mo>∼</mo><msub><mi>π</mi><mi>θ</mi></msub></mrow></msub><mrow><mo fence="true">[</mo><munderover><mo>∑</mo><mrow><mi>t</mi><mo>=</mo><mn>0</mn></mrow><mi>T</mi></munderover><msub><mi mathvariant="normal">∇</mi><mi>θ</mi></msub><mi>log</mi><mo>⁡</mo><msub><mi>π</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><msub><mi>a</mi><mi>t</mi></msub><mi mathvariant="normal">∣</mi><msub><mi>s</mi><mi>t</mi></msub><mo stretchy="false">)</mo><mo>⋅</mo><mi>R</mi><mo stretchy="false">(</mo><mi>τ</mi><mo stretchy="false">)</mo><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">\nabla_\theta J(\theta) = \mathbb{E}_{\tau \sim \pi_\theta} \left[ \sum_{t=0}^T \nabla_\theta \log \pi_\theta(a_t | s_t) \cdot R(\tau) \right]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord">∇</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord mathnormal">J</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathbb">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">τ</span><span class="mrel mtight">∼</span><span class="mord mtight"><span class="mord mathnormal mtight">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size4">[</span></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mrel mtight">=</span><span class="mord mtight">0</span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="mord"><span class="mord">∇</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mop">log</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span><span class="mord mathnormal">R</span><span class="mopen">(</span><span class="mord mathnormal">τ</span><span class="mclose">)</span><span class="mclose delimcenter"><span class="delimsizing size4">]</span></span></span></span></span></span></span><!----></div> <p>Where:</p> <ul><li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi></mrow><annotation encoding="application/x-tex">\theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">θ</span></span></span></span><!----></span>: Policy parameters</li> <li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">τ</span></span></span></span><!----></span>: Trajectory (sequence of states, actions)</li> <li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mo stretchy="false">(</mo><mi>τ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">R(\tau)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">R</span><span class="mopen">(</span><span class="mord mathnormal">τ</span><span class="mclose">)</span></span></span></span><!----></span>: Return (total reward)</li></ul> <p><strong>Intuition:</strong> Increase probability of actions that led to high reward.</p> <h2 id="reinforce-algorithm"><a href="#reinforce-algorithm">REINFORCE Algorithm</a></h2> <p>The simplest policy gradient algorithm:</p> <ol><li>Collect trajectories by running policy (\pi_\theta)</li> <li>Compute returns (R(\tau)) for each trajectory</li> <li>Update policy: (\theta \leftarrow \theta + \alpha \nabla<em>\theta \log \pi</em>\theta \cdot R(\tau))</li></ol> <p><strong>Problem:</strong> High variance! Single trajectory return is noisy.</p> <p><strong>Solution:</strong> Baselines and advantage estimation.</p> <h2 id="variance-reduction-baselines"><a href="#variance-reduction-baselines">Variance Reduction: Baselines</a></h2> <p><strong>Key insight:</strong> Subtract a baseline from returns without biasing the gradient.</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi mathvariant="normal">∇</mi><mi>θ</mi></msub><mi>J</mi><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi mathvariant="double-struck">E</mi><mi>τ</mi></msub><mrow><mo fence="true">[</mo><msub><mi mathvariant="normal">∇</mi><mi>θ</mi></msub><mi>log</mi><mo>⁡</mo><msub><mi>π</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><msub><mi>a</mi><mi>t</mi></msub><mi mathvariant="normal">∣</mi><msub><mi>s</mi><mi>t</mi></msub><mo stretchy="false">)</mo><mo>⋅</mo><mo stretchy="false">(</mo><mi>R</mi><mo stretchy="false">(</mo><mi>τ</mi><mo stretchy="false">)</mo><mo>−</mo><mi>b</mi><mo stretchy="false">(</mo><msub><mi>s</mi><mi>t</mi></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">\nabla_\theta J(\theta) = \mathbb{E}_{\tau} \left[ \nabla_\theta \log \pi_\theta(a_t | s_t) \cdot (R(\tau) - b(s_t)) \right]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord">∇</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord mathnormal">J</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathbb">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">τ</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter">[</span><span class="mord"><span class="mord">∇</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mop">log</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span><span class="mopen">(</span><span class="mord mathnormal">R</span><span class="mopen">(</span><span class="mord mathnormal">τ</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord mathnormal">b</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">))</span><span class="mclose delimcenter">]</span></span></span></span></span></span><!----></div> <p><strong>Common baseline:</strong> Value function <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>V</mi><mo stretchy="false">(</mo><msub><mi>s</mi><mi>t</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">V(s_t)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">V</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span> leads to <strong>actor-critic</strong>.</p> <h2 id="actor-critic-architecture"><a href="#actor-critic-architecture">Actor-Critic Architecture</a></h2> <p><strong>Two networks:</strong></p> <ul><li><strong>Actor:</strong> Policy <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><mi>a</mi><mi mathvariant="normal">∣</mi><mi>s</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\pi_\theta(a|s)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">s</span><span class="mclose">)</span></span></span></span><!----></span> (what to do)</li> <li><strong>Critic:</strong> Value function <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>V</mi><mi>ϕ</mi></msub><mo stretchy="false">(</mo><mi>s</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">V_\phi(s)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">ϕ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mclose">)</span></span></span></span><!----></span> (how good is this state)</li></ul> <p><strong>Advantage:</strong> <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo stretchy="false">(</mo><mi>s</mi><mo separator="true">,</mo><mi>a</mi><mo stretchy="false">)</mo><mo>=</mo><mi>Q</mi><mo stretchy="false">(</mo><mi>s</mi><mo separator="true">,</mo><mi>a</mi><mo stretchy="false">)</mo><mo>−</mo><mi>V</mi><mo stretchy="false">(</mo><mi>s</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">A(s, a) = Q(s, a) - V(s)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">Q</span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">V</span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mclose">)</span></span></span></span><!----></span></p> <p><strong>Update rule:</strong></p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>θ</mi><mo>←</mo><mi>θ</mi><mo>+</mo><mi>α</mi><msub><mi mathvariant="normal">∇</mi><mi>θ</mi></msub><mi>log</mi><mo>⁡</mo><msub><mi>π</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><mi>a</mi><mi mathvariant="normal">∣</mi><mi>s</mi><mo stretchy="false">)</mo><mo>⋅</mo><mi>A</mi><mo stretchy="false">(</mo><mi>s</mi><mo separator="true">,</mo><mi>a</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\theta \leftarrow \theta + \alpha \nabla_\theta \log \pi_\theta(a|s) \cdot A(s, a)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">θ</span><span class="mspace"></span><span class="mrel">←</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">θ</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">α</span><span class="mord"><span class="mord">∇</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mop">log</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">s</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">a</span><span class="mclose">)</span></span></span></span></span><!----></div> <p><strong>Benefit:</strong> Lower variance than pure REINFORCE, faster learning.</p> <h2 id="generalized-advantage-estimation-gae"><a href="#generalized-advantage-estimation-gae">Generalized Advantage Estimation (GAE)</a></h2> <p><strong>Problem:</strong> Bias-variance trade-off in advantage estimation.</p> <p><strong>GAE solution:</strong> Exponentially weighted average of n-step advantages.</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mover accent="true"><mi>A</mi><mo>^</mo></mover><mi>t</mi></msub><mo>=</mo><munderover><mo>∑</mo><mrow><mi>l</mi><mo>=</mo><mn>0</mn></mrow><mi mathvariant="normal">∞</mi></munderover><mo stretchy="false">(</mo><mi>γ</mi><mi>λ</mi><msup><mo stretchy="false">)</mo><mi>l</mi></msup><msub><mi>δ</mi><mrow><mi>t</mi><mo>+</mo><mi>l</mi></mrow></msub></mrow><annotation encoding="application/x-tex">\hat{A}_t = \sum_{l=0}^\infty (\gamma \lambda)^l \delta_{t+l}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">A</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">l</span><span class="mrel mtight">=</span><span class="mord mtight">0</span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">γλ</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">l</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">δ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mbin mtight">+</span><span class="mord mathnormal mtight">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><!----></div> <p>Where <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>δ</mi><mi>t</mi></msub><mo>=</mo><msub><mi>r</mi><mi>t</mi></msub><mo>+</mo><mi>γ</mi><mi>V</mi><mo stretchy="false">(</mo><msub><mi>s</mi><mrow><mi>t</mi><mo>+</mo><mn>1</mn></mrow></msub><mo stretchy="false">)</mo><mo>−</mo><mi>V</mi><mo stretchy="false">(</mo><msub><mi>s</mi><mi>t</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\delta_t = r_t + \gamma V(s_{t+1}) - V(s_t)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">δ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">γV</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">V</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span> (TD error).</p> <p><strong>Tuning <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi></mrow><annotation encoding="application/x-tex">\lambda</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">λ</span></span></span></span><!----></span>:</strong></p> <ul><li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\lambda = 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">λ</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span>: Low variance, high bias (TD learning)</li> <li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\lambda = 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">λ</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span>: High variance, low bias (Monte Carlo)</li> <li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi><mo>=</mo><mn>0.95</mn></mrow><annotation encoding="application/x-tex">\lambda = 0.95</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">λ</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0.95</span></span></span></span><!----></span>: Good default</li></ul> <h2 id="key-resources"><a href="#key-resources">Key Resources</a></h2> <h3 id="ƒôü-essential-reading"><a href="#ƒôü-essential-reading">≡ƒôÜ Essential Reading</a></h3> <p><strong>REINFORCE Algorithm Tutorial</strong> (Substack)<br/> <a href="https://substack.com/inbox/post/170790602" rel="nofollow noopener noreferrer external" target="_blank">https://substack.com/inbox/post/170790602</a></p> <p>Clear walkthrough of the REINFORCE algorithm with derivations.</p> <p><strong>The RLHF Book</strong><br/> <a href="https://rlhfbook.com/" rel="nofollow noopener noreferrer external" target="_blank">https://rlhfbook.com/</a></p> <p>Comprehensive resource for RL in the context of LLM post-training. Covers policy gradients, PPO, and RLHF applications. <strong>Essential for applied RL.</strong></p> <h3 id="ƒôû-books"><a href="#ƒôû-books">≡ƒôû Books</a></h3> <p><strong>Foundations of Deep Reinforcement Learning</strong> by Graesser &amp; Keng</p> <p>Practical, code-first approach to deep RL. Includes PyTorch implementations of REINFORCE, actor-critic, and PPO.</p> <h2 id="learning-path"><a href="#learning-path">Learning Path</a></h2> <h3 id="phase-1-theory-4-hours"><a href="#phase-1-theory-4-hours">Phase 1: Theory (4 hours)</a></h3> <ol><li>Derive policy gradient theorem from scratch</li> <li>Read REINFORCE tutorial</li> <li>Work through actor-critic derivation</li></ol> <h3 id="phase-2-implementation-4-hours"><a href="#phase-2-implementation-4-hours">Phase 2: Implementation (4 hours)</a></h3> <ol><li>Implement REINFORCE on CartPole</li> <li>Add baseline (value function)</li> <li>Implement actor-critic</li> <li>Compare variance: REINFORCE vs actor-critic</li></ol> <h3 id="phase-3-deep-dive-2-hours"><a href="#phase-3-deep-dive-2-hours">Phase 3: Deep Dive (2 hours)</a></h3> <ol><li>Read RLHF Book chapter on policy gradients</li> <li>Implement GAE</li> <li>Understand connection to PPO (next node)</li></ol> <h2 id="common-pitfalls"><a href="#common-pitfalls">Common Pitfalls</a></h2> <p>Γ¥î <strong>Forgetting the log:</strong> It’s <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∇</mi><mi>log</mi><mo>⁡</mo><mi>π</mi></mrow><annotation encoding="application/x-tex">\nabla \log \pi</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∇</span><span class="mspace"></span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">π</span></span></span></span><!----></span>, not <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∇</mi><mi>π</mi></mrow><annotation encoding="application/x-tex">\nabla \pi</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∇</span><span class="mord mathnormal">π</span></span></span></span><!----></span>.</p> <p>Γ¥î <strong>Biased baselines:</strong> Only state-dependent baselines are unbiased.</p> <p>Γ¥î <strong>Ignoring variance:</strong> High variance = slow/unstable learning. Always use baselines.</p> <p>Γ¥î <strong>Wrong advantage signs:</strong> Positive advantage - increase action probability.</p> <h2 id="next-steps"><a href="#next-steps">Next Steps</a></h2> <ul><li><ul><li><strong>PPO from Scratch:</strong> The de facto standard policy gradient algorithm</li></ul></li> <li><ul><li><strong>Preference Data &amp; Eval Design:</strong> How to get reward signals from human preferences</li></ul></li></ul> <h2 id="assessment-criteria"><a href="#assessment-criteria">Assessment Criteria</a></h2> <p>Γ£à You understand this node when you can:</p> <ul><li>Derive the policy gradient theorem</li> <li>Implement REINFORCE from scratch</li> <li>Explain why baselines reduce variance without bias</li> <li>Code up an actor-critic agent</li> <li>Implement GAE and tune (\lambda)</li></ul><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="yggdrasil" scheme="https://https:///?tags=yggdrasil" />
    <category term="rl" scheme="https://https:///?tags=rl" />
    <category term="REINFORCE" scheme="https://https:///?tags=REINFORCE" />
    <category term="actor-critic" scheme="https://https:///?tags=actor-critic" />
    <category term="policy-gradient" scheme="https://https:///?tags=policy-gradient" />
    <category term="RL" scheme="https://https:///?tags=RL" />
  </entry>
  <entry>
    <title type="html"><![CDATA[PPO from Scratch]]></title>
    <link href="https://https:///growth/2026/ppo-from-scratch" />
    <id>https://https:///growth/2026/ppo-from-scratch</id>
    <published>2025-12-31T00:00:00.000Z</published>
    <updated>2025-12-31T00:00:00.000Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="overview"><a href="#overview">Overview</a></h2> <p>Implement Proximal Policy Optimization (PPO) from scratch and build strong evaluation discipline. PPO is the workhorse of modern RLHF and the foundation for understanding post-training.</p> <p><strong>Goal:</strong> Build a production-grade PPO implementation you can trust and extend.</p> <h2 id="key-concepts"><a href="#key-concepts">Key Concepts</a></h2> <!--[0--><div class="concept-checklist my-6 svelte-zxd1c0"><div class="flex justify-between items-center mb-4"><h3 class="text-xl font-bold flex items-center gap-2">📋 Concepts <!--[-1--><!--]--></h3> <div class="text-sm opacity-70">0 / 7 mastered</div></div> <div class="progress-bar-container mb-4"><progress class="progress progress-primary w-full" value="0" max="100">0%</progress></div> <div class="space-y-2"><!--[--><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">PPO Clipped Surrogate Objective</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Importance Sampling &amp; Probability Ratios</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">KL Penalty vs Clipping</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Full PPO Implementation</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Hyperparameter Tuning (clip_eps, GAE lambda)</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Evaluation Discipline &amp; Debugging</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">GRPO: Group Relative Policy Optimization</span> <!--[-1--><!--]--></label><!--]--></div> <!--[-1--><!--]--></div><!--]--><!----> <h2 id="why-ppo"><a href="#why-ppo">Why PPO?</a></h2> <p><strong>Problem with vanilla policy gradients:</strong> Large policy updates can catastrophically degrade performance.</p> <p><strong>PPO solution:</strong> Constrain policy updates to a “trust region” using a clipped objective.</p> <h2 id="the-ppo-objective"><a href="#the-ppo-objective">The PPO Objective</a></h2> <p><strong>Clipped surrogate objective:</strong></p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msup><mi>L</mi><mrow><mi>C</mi><mi>L</mi><mi>I</mi><mi>P</mi></mrow></msup><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi mathvariant="double-struck">E</mi><mi>t</mi></msub><mrow><mo fence="true">[</mo><mi>min</mi><mo>⁡</mo><mo stretchy="false">(</mo><msub><mi>r</mi><mi>t</mi></msub><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><msub><mover accent="true"><mi>A</mi><mo>^</mo></mover><mi>t</mi></msub><mo separator="true">,</mo><mtext>clip</mtext><mo stretchy="false">(</mo><msub><mi>r</mi><mi>t</mi></msub><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo separator="true">,</mo><mn>1</mn><mo>−</mo><mi>ϵ</mi><mo separator="true">,</mo><mn>1</mn><mo>+</mo><mi>ϵ</mi><mo stretchy="false">)</mo><msub><mover accent="true"><mi>A</mi><mo>^</mo></mover><mi>t</mi></msub><mo stretchy="false">)</mo><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">L^{CLIP}(\theta) = \mathbb{E}_t \left[ \min(r_t(\theta) \hat{A}_t, \text{clip}(r_t(\theta), 1-\epsilon, 1+\epsilon) \hat{A}_t) \right]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">C</span><span class="mord mathnormal mtight">L</span><span class="mord mathnormal mtight">I</span><span class="mord mathnormal mtight">P</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathbb">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size2">[</span></span><span class="mop">min</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mord"><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">A</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord text"><span class="mord">clip</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">1</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord mathnormal">ϵ</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">1</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span><span class="mord mathnormal">ϵ</span><span class="mclose">)</span><span class="mord"><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">A</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mclose delimcenter"><span class="delimsizing size2">]</span></span></span></span></span></span></span><!----></div> <p>Where:</p> <ul><li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>r</mi><mi>t</mi></msub><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><mfrac><mrow><msub><mi>π</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><msub><mi>a</mi><mi>t</mi></msub><mi mathvariant="normal">∣</mi><msub><mi>s</mi><mi>t</mi></msub><mo stretchy="false">)</mo></mrow><mrow><msub><mi>π</mi><msub><mi>θ</mi><mtext>old</mtext></msub></msub><mo stretchy="false">(</mo><msub><mi>a</mi><mi>t</mi></msub><mi mathvariant="normal">∣</mi><msub><mi>s</mi><mi>t</mi></msub><mo stretchy="false">)</mo></mrow></mfrac></mrow><annotation encoding="application/x-tex">r_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{\text{old}}}(a_t|s_t)}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">θ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">old</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord mtight">∣</span><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose mtight">)</span></span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord mtight">∣</span><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose mtight">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span><!----></span>: Probability ratio (importance sampling)</li> <li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mover accent="true"><mi>A</mi><mo>^</mo></mover><mi>t</mi></msub></mrow><annotation encoding="application/x-tex">\hat{A}_t</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">A</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>: Advantage estimate (from GAE)</li> <li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding="application/x-tex">\epsilon</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">ϵ</span></span></span></span><!----></span>: Clip range (typically 0.2)</li></ul> <p><strong>Intuition:</strong> If ratio greater than 1+╬╡ or less than 1-╬╡, clip it. Don’t let policy change too much.</p> <h2 id="implementation-checklist"><a href="#implementation-checklist">Implementation Checklist</a></h2> <h3 id="core-components"><a href="#core-components">Core Components</a></h3> <p>Γ£à <strong>Policy network</strong> (<span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mi>θ</mi></msub></mrow><annotation encoding="application/x-tex">\pi_\theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>): Output action probabilities<br/> Γ£à <strong>Value network</strong> (<span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>V</mi><mi>ϕ</mi></msub></mrow><annotation encoding="application/x-tex">V_\phi</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">ϕ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>): Estimate state values<br/> Γ£à <strong>Advantage computation</strong> (GAE with <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi><mo>=</mo><mn>0.95</mn></mrow><annotation encoding="application/x-tex">\lambda = 0.95</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">λ</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0.95</span></span></span></span><!----></span>)<br/> Γ£à <strong>Probability ratio</strong>: <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>r</mi><mi>t</mi></msub><mo>=</mo><msub><mi>π</mi><mtext>new</mtext></msub><mi mathvariant="normal">/</mi><msub><mi>π</mi><mtext>old</mtext></msub></mrow><annotation encoding="application/x-tex">r_t = \pi_{\text{new}} / \pi_{\text{old}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">new</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">old</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span><br/> Γ£à <strong>Clipped objective</strong>: <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>min</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>r</mi><mo>⋅</mo><mi>A</mi><mo separator="true">,</mo><mtext>clip</mtext><mo stretchy="false">(</mo><mi>r</mi><mo separator="true">,</mo><mn>1</mn><mo>−</mo><mi>ϵ</mi><mo separator="true">,</mo><mn>1</mn><mo>+</mo><mi>ϵ</mi><mo stretchy="false">)</mo><mo>⋅</mo><mi>A</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\min(r \cdot A, \text{clip}(r, 1-\epsilon, 1+\epsilon) \cdot A)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord mathnormal">r</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord text"><span class="mord">clip</span></span><span class="mopen">(</span><span class="mord mathnormal">r</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">1</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">ϵ</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">1</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">ϵ</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span><span class="mclose">)</span></span></span></span><!----></span><br/> Γ£à <strong>Value loss</strong>: MSE between predicted and actual returns<br/> Γ£à <strong>Entropy bonus</strong>: Encourage exploration</p> <h3 id="training-loop"><a href="#training-loop">Training Loop</a></h3> <ol><li><strong>Collect rollouts</strong> using current policy</li> <li><strong>Compute advantages</strong> using GAE</li> <li><strong>Multiple epochs</strong> of minibatch updates (e.g., 4 epochs)</li> <li><strong>Update policy</strong> with clipped objective</li> <li><strong>Update value function</strong> with MSE loss</li> <li><strong>Log metrics</strong>: KL divergence, clip fraction, explained variance</li></ol> <h2 id="kl-penalty-vs-clipping"><a href="#kl-penalty-vs-clipping">KL Penalty vs Clipping</a></h2> <p><strong>Two ways to constrain policy updates:</strong></p> <ol><li><strong>Clipping (PPO-Clip):</strong> Hard constraint via clipping</li> <li><strong>KL Penalty (PPO-KL):</strong> Soft constraint via penalty term</li></ol> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msup><mi>L</mi><mrow><mi>K</mi><mi>L</mi></mrow></msup><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi mathvariant="double-struck">E</mi><mi>t</mi></msub><mrow><mo fence="true">[</mo><msub><mi>r</mi><mi>t</mi></msub><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><msub><mover accent="true"><mi>A</mi><mo>^</mo></mover><mi>t</mi></msub><mo>−</mo><mi>β</mi><mo>⋅</mo><mtext>KL</mtext><mo stretchy="false">(</mo><msub><mi>π</mi><msub><mi>θ</mi><mtext>old</mtext></msub></msub><mi mathvariant="normal">∣</mi><mi mathvariant="normal">∣</mi><msub><mi>π</mi><mi>θ</mi></msub><mo stretchy="false">)</mo><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">L^{KL}(\theta) = \mathbb{E}_t \left[ r_t(\theta) \hat{A}_t - \beta \cdot \text{KL}(\pi_{\theta_{\text{old}}} || \pi_\theta) \right]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">K</span><span class="mord mathnormal mtight">L</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathbb">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size2">[</span></span><span class="mord"><span class="mord mathnormal">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mord"><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">A</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord mathnormal">β</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span><span class="mord text"><span class="mord">KL</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">θ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">old</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord">∣∣</span><span class="mord"><span class="mord mathnormal">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mclose delimcenter"><span class="delimsizing size2">]</span></span></span></span></span></span></span><!----></div> <p><strong>In practice:</strong> PPO-Clip is simpler and works just as well. Use that.</p> <h2 id="hyperparameter-tuning"><a href="#hyperparameter-tuning">Hyperparameter Tuning</a></h2> <p><strong>Critical hyperparameters:</strong></p> <ul><li><strong>clip_eps (╬╡):</strong> 0.1ΓÇô0.3 (default 0.2)</li> <li><strong>GAE lambda (╬╗):</strong> 0.9ΓÇô0.99 (default 0.95)</li> <li><strong>Learning rate:</strong> 3e-4 (tune with lr schedule)</li> <li><strong>Minibatch size:</strong> 64ΓÇô256</li> <li><strong>Number of epochs:</strong> 3ΓÇô10 (watch for overfitting)</li> <li><strong>Entropy coefficient:</strong> 0.01 (decay over training)</li></ul> <p><strong>Tuning strategy:</strong> Start with defaults, watch KL divergence and clip fraction.</p> <h2 id="evaluation-discipline"><a href="#evaluation-discipline">Evaluation Discipline</a></h2> <h3 id="metrics-to-track"><a href="#metrics-to-track">Metrics to Track</a></h3> <p>Γ£à <strong>Episode return</strong> (mean, std, min, max)<br/> Γ£à <strong>KL divergence</strong> (should be small, less than 0.05)<br/> Γ£à <strong>Clip fraction</strong> (what % of updates were clipped)<br/> Γ£à <strong>Explained variance</strong> (how well V predicts returns)<br/> Γ£à <strong>Entropy</strong> (should decay slowly)<br/> Γ£à <strong>Policy loss, value loss</strong></p> <h3 id="debugging-checklist"><a href="#debugging-checklist">Debugging Checklist</a></h3> <p>Γ¥î <strong>KL divergence exploding?</strong> Reduce learning rate or clip_eps<br/> Γ¥î <strong>Clip fraction = 1?</strong> Policy changing too fast, reduce LR<br/> Γ¥î <strong>Explained variance negative?</strong> Value function broken, check value loss<br/> Γ¥î <strong>Entropy going to 0 too fast?</strong> Increase entropy coefficient</p> <h2 id="grpo-group-relative-policy-optimization"><a href="#grpo-group-relative-policy-optimization">GRPO: Group Relative Policy Optimization</a></h2> <p><strong>Recent variant:</strong> Instead of comparing to a value function baseline, use <strong>group-wise relative rewards</strong>.</p> <p><strong>Idea:</strong> Normalize rewards within each batch/group before computing advantages.</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mover accent="true"><mi>A</mi><mo>^</mo></mover><mi>i</mi></msub><mo>=</mo><msub><mi>R</mi><mi>i</mi></msub><mo>−</mo><mfrac><mn>1</mn><mi>G</mi></mfrac><munder><mo>∑</mo><mrow><mi>j</mi><mo>∈</mo><mtext>group</mtext></mrow></munder><msub><mi>R</mi><mi>j</mi></msub></mrow><annotation encoding="application/x-tex">\hat{A}_i = R_i - \frac{1}{G} \sum_{j \in \text{group}} R_j</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord mathnormal">A</span></span><span class="pstrut"><span class="accent-body"><span class="mord">^</span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">G</span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">j</span><span class="mrel mtight">∈</span><span class="mord text mtight"><span class="mord mtight">group</span></span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><!----></div> <p><strong>Benefit:</strong> Simpler (no value function), more stable for some tasks.</p> <h2 id="key-resources"><a href="#key-resources">Key Resources</a></h2> <h3 id="ƒôü-essential-reading"><a href="#ƒôü-essential-reading">≡ƒôÜ Essential Reading</a></h3> <p><strong>PPO and GRPO Comparison</strong> (Yugeten)<br/> <a href="https://yugeten.github.io/posts/2025/01/ppogrpo/" rel="nofollow noopener noreferrer external" target="_blank">https://yugeten.github.io/posts/2025/01/ppogrpo/</a></p> <p>Deep dive into PPO implementation details and comparison with GRPO. <strong>Must-read for implementation.</strong></p> <p><strong>The RLHF Book</strong><br/> <a href="https://rlhfbook.com/" rel="nofollow noopener noreferrer external" target="_blank">https://rlhfbook.com/</a></p> <p>Chapters on PPO for LLM post-training with code examples.</p> <h3 id="ƒôû-books"><a href="#ƒôû-books">≡ƒôû Books</a></h3> <p><strong>Foundations of Deep Reinforcement Learning</strong> by Graesser &amp; Keng</p> <p>Chapter on PPO with PyTorch implementation.</p> <h2 id="learning-path"><a href="#learning-path">Learning Path</a></h2> <h3 id="phase-1-understand-the-theory-4-hours"><a href="#phase-1-understand-the-theory-4-hours">Phase 1: Understand the Theory (4 hours)</a></h3> <ol><li>Review importance sampling &amp; probability ratios</li> <li>Derive clipped objective from first principles</li> <li>Read Yugeten PPO/GRPO post</li></ol> <h3 id="phase-2-implement-8-hours"><a href="#phase-2-implement-8-hours">Phase 2: Implement (8 hours)</a></h3> <ol><li>Implement PPO on CartPole or MuJoCo</li> <li>Track all key metrics (KL, clip fraction, explained variance)</li> <li>Debug until you get smooth learning curves</li> <li>Compare to baseline implementation (e.g., Stable-Baselines3)</li></ol> <h3 id="phase-3-deep-dive-3-hours"><a href="#phase-3-deep-dive-3-hours">Phase 3: Deep Dive (3 hours)</a></h3> <ol><li>Implement GRPO variant</li> <li>Compare PPO vs GRPO on same task</li> <li>Read RLHF Book chapters on LLM post-training with PPO</li></ol> <h2 id="common-pitfalls"><a href="#common-pitfalls">Common Pitfalls</a></h2> <p>Γ¥î <strong>Not normalizing advantages:</strong> Always normalize per-batch.</p> <p>Γ¥î <strong>Too many epochs:</strong> Overfitting leads to high KL divergence.</p> <p>Γ¥î <strong>Forgetting old policy probabilities:</strong> Store log probs from rollouts!</p> <p>Γ¥î <strong>Wrong advantage signs:</strong> Double-check your advantage computation.</p> <p>Γ¥î <strong>Ignoring clip fraction:</strong> If it’s 0 or 1, something’s wrong.</p> <h2 id="next-steps"><a href="#next-steps">Next Steps</a></h2> <ul><li><strong>DPO-Family Competence:</strong> Modern alternatives to PPO (offline RL)</li> <li><strong>Online Loops &amp; Stability:</strong> Iterative PPO training with reward model updates</li></ul> <h2 id="assessment-criteria"><a href="#assessment-criteria">Assessment Criteria</a></h2> <p>Γ£à You understand this node when you can:</p> <ul><li>Implement PPO from scratch with all bells and whistles</li> <li>Explain why clipping constrains policy updates</li> <li>Tune hyperparameters based on logged metrics</li> <li>Debug training instabilities (KL explosion, clip fraction issues)</li> <li>Compare PPO to GRPO and articulate trade-offs</li></ul><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="yggdrasil" scheme="https://https:///?tags=yggdrasil" />
    <category term="rl" scheme="https://https:///?tags=rl" />
    <category term="PPO" scheme="https://https:///?tags=PPO" />
    <category term="implementation" scheme="https://https:///?tags=implementation" />
    <category term="evaluation" scheme="https://https:///?tags=evaluation" />
    <category term="RL" scheme="https://https:///?tags=RL" />
    <category term="GRPO" scheme="https://https:///?tags=GRPO" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Ultra-Scale Heuristics Distillation]]></title>
    <link href="https://https:///growth/2026/ultra-scale-heuristics" />
    <id>https://https:///growth/2026/ultra-scale-heuristics</id>
    <published>2025-12-31T00:00:00.000Z</published>
    <updated>2025-12-31T00:00:00.000Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="overview"><a href="#overview">Overview</a></h2> <p>Your <strong>living playbook</strong> for ultra-scale distributed training. Distill practical heuristics for 5D parallelism, overlap strategies, gradient bucketing, and the ZeRO + Tensor Parallelism interplay.</p> <p><strong>This is the “scale bible”</strong> ΓÇö a constantly updated reference as you encounter real bottlenecks.</p> <h2 id="key-concepts"><a href="#key-concepts">Key Concepts</a></h2> <!--[0--><div class="concept-checklist my-6 svelte-zxd1c0"><div class="flex justify-between items-center mb-4"><h3 class="text-xl font-bold flex items-center gap-2">📋 Concepts <!--[-1--><!--]--></h3> <div class="text-sm opacity-70">0 / 7 mastered</div></div> <div class="progress-bar-container mb-4"><progress class="progress progress-primary w-full" value="0" max="100">0%</progress></div> <div class="space-y-2"><!--[--><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">5D Parallelism: DP + TP + PP + SP + CP</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Overlap: Compute, Communication, I/O</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Gradient Bucketing &amp; AllReduce Optimization</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">ZeRO + Tensor Parallelism Interplay</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Memory Budgeting: Activation, Gradients, Optimizer States</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Communication-Compute Ratio Analysis</span> <!--[-1--><!--]--></label><label class="flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-all hover:bg-base-200"><input type="checkbox" class="checkbox checkbox-primary"/> <span class="flex-1">Empirical Scaling Laws for Parallelism</span> <!--[-1--><!--]--></label><!--]--></div> <!--[-1--><!--]--></div><!--]--><!----> <h2 id="the-5d-parallelism-stack"><a href="#the-5d-parallelism-stack">The 5D Parallelism Stack</a></h2> <p>Modern large-scale training combines multiple parallelism strategies:</p> <ol><li><strong>Data Parallelism (DP):</strong> Replicate model across workers</li> <li><strong>Tensor Parallelism (TP):</strong> Shard individual layers across GPUs</li> <li><strong>Pipeline Parallelism (PP):</strong> Split model layers across stages</li> <li><strong>Sequence Parallelism (SP):</strong> Shard sequence dimension for long-context models</li> <li><strong>Context Parallelism (CP):</strong> Ring-style attention for ultra-long sequences</li></ol> <p><strong>The art:</strong> Knowing which dimensions to parallelize for your model + hardware.</p> <h2 id="overlap-strategies"><a href="#overlap-strategies">Overlap Strategies</a></h2> <h3 id="compute-communication-overlap"><a href="#compute-communication-overlap">Compute-Communication Overlap</a></h3> <p>Key insight: <strong>Don’t wait for communication to finish before computing.</strong></p> <ul><li><strong>Gradient bucketing:</strong> AllReduce gradients in buckets as they’re computed</li> <li><strong>Pipeline bubbles:</strong> Fill bubbles with microbatches</li> <li><strong>Prefetching:</strong> Load next batch while current batch is computing</li></ul> <h3 id="zero--tensor-parallelism-interplay"><a href="#zero--tensor-parallelism-interplay">ZeRO + Tensor Parallelism Interplay</a></h3> <p><strong>Naive approach:</strong> Apply ZeRO-3 + TP independently leads to excessive communication</p> <p><strong>Better approach:</strong></p> <ul><li>Use TP within nodes (high bandwidth)</li> <li>Use ZeRO across nodes (lower bandwidth)</li> <li>Hybrid sharding: <code>HYBRID_SHARD</code> in PyTorch FSDP</li></ul> <h2 id="gradient-bucketing"><a href="#gradient-bucketing">Gradient Bucketing</a></h2> <p><strong>Problem:</strong> Waiting for all gradients before AllReduce wastes time.</p> <p><strong>Solution:</strong> Bucket gradients and start AllReduce as soon as each bucket is ready.</p> <p><strong>Tuning:</strong> Bucket size trades off:</p> <ul><li>Small buckets: more overlap, more kernel launches</li> <li>Large buckets: less overlap, fewer kernel launches</li></ul> <p><strong>Heuristic:</strong> 25MB buckets is a good default for most models.</p> <h2 id="memory-budgeting"><a href="#memory-budgeting">Memory Budgeting</a></h2> <p>For a transformer with N parameters:</p> <ul><li><strong>Parameters:</strong> N</li> <li><strong>Gradients:</strong> N</li> <li><strong>Optimizer states (AdamW):</strong> 2N (momentum + variance)</li> <li><strong>Activations:</strong> Depends on batch size, sequence length, hidden size</li></ul> <p><strong>ZeRO-3 savings:</strong> (N + N + 2N) / num_gpus = 4N / num_gpus</p> <p><strong>Activation checkpointing:</strong> Trade compute for memory (recompute activations in backward pass)</p> <h2 id="communication-compute-ratio"><a href="#communication-compute-ratio">Communication-Compute Ratio</a></h2> <p><strong>Good scaling:</strong> Communication time much less than Compute time</p> <p><strong>Rule of thumb:</strong> Aim for greater than 10:1 compute-to-communication ratio.</p> <p><strong>How to achieve:</strong></p> <ul><li>Increase batch size (more compute per communication)</li> <li>Use faster interconnect (NVLink better than PCIe, InfiniBand better than Ethernet)</li> <li>Reduce communication frequency (gradient accumulation)</li></ul> <h2 id="key-resources"><a href="#key-resources">Key Resources</a></h2> <h3 id="ƒôü-essential-playbooks"><a href="#ƒôü-essential-playbooks">≡ƒôÜ Essential Playbooks</a></h3> <p><strong>Nanotron Ultra-Scale Playbook</strong><br/> <a href="https://huggingface.co/spaces/nanotron/ultrascale-playbook" rel="nofollow noopener noreferrer external" target="_blank">https://huggingface.co/spaces/nanotron/ultrascale-playbook</a></p> <p>The definitive reference for ultra-scale training heuristics. Covers 5D parallelism interplay, overlap strategies, and practical recipes for scaling to thousands of GPUs. <strong>This is your bible.</strong></p> <p><strong>Smol Training Playbook</strong> (complementary)<br/> <a href="https://huggingface.co/spaces/HuggingFaceTB/smol-training-playbook" rel="nofollow noopener noreferrer external" target="_blank">https://huggingface.co/spaces/HuggingFaceTB/smol-training-playbook</a></p> <h2 id="learning-path"><a href="#learning-path">Learning Path</a></h2> <h3 id="phase-1-understand-the-dimensions-10-hours"><a href="#phase-1-understand-the-dimensions-10-hours">Phase 1: Understand the Dimensions (10 hours)</a></h3> <ol><li>Read Nanotron Ultra-Scale Playbook cover-to-cover</li> <li>Map each parallelism type to a concrete use case</li> <li>Sketch communication patterns for hybrid TP+ZeRO</li></ol> <h3 id="phase-2-hands-on-profiling-12-hours"><a href="#phase-2-hands-on-profiling-12-hours">Phase 2: Hands-On Profiling (12 hours)</a></h3> <ol><li>Profile a 7B model with different parallelism configs</li> <li>Measure communication-compute ratio</li> <li>Experiment with gradient bucketing sizes</li> <li>Compare memory usage: ZeRO-1 vs ZeRO-2 vs ZeRO-3</li></ol> <h3 id="phase-3-build-your-heuristics-library-8-hours"><a href="#phase-3-build-your-heuristics-library-8-hours">Phase 3: Build Your Heuristics Library (8 hours)</a></h3> <ol><li>Document your own scaling rules for your hardware</li> <li>Create a decision tree: “Given model size X and N GPUs, use…”</li> <li>Benchmark and record actual throughput numbers</li></ol> <h2 id="practical-heuristics-living-document"><a href="#practical-heuristics-living-document">Practical Heuristics (Living Document)</a></h2> <h3 id="model-size-decision-tree"><a href="#model-size-decision-tree">Model Size Decision Tree</a></h3> <p><strong>Under 1B params:</strong></p> <ul><li>Pure DP (simplest, fastest)</li> <li>ZeRO-1 if memory tight</li></ul> <p><strong>1B - 13B params:</strong></p> <ul><li>DP + ZeRO-2</li> <li>Consider TP=2 within nodes if very memory constrained</li></ul> <p><strong>13B - 70B params:</strong></p> <ul><li>DP + ZeRO-3 or FSDP</li> <li>TP=2 or TP=4 within nodes</li> <li>PP=2 if model still doesn’t fit</li></ul> <p><strong>Over 70B params:</strong></p> <ul><li>Full 5D parallelism</li> <li>TP=4 or TP=8 within nodes</li> <li>PP=4+ across nodes</li> <li>ZeRO-3 or hybrid sharding</li> <li>Consider SP/CP for long-context variants</li></ul> <h3 id="overlap-checklist"><a href="#overlap-checklist">Overlap Checklist</a></h3> <p>Γ£à Gradient bucketing enabled (25MB buckets)<br/> Γ£à Data prefetching in dataloader<br/> Γ£à Pipeline parallelism with microbatches (8-16 microbatches)<br/> Γ£à Activation checkpointing for memory-bound models<br/> Γ£à Mixed precision (bf16) to reduce communication volume</p> <h2 id="common-pitfalls"><a href="#common-pitfalls">Common Pitfalls</a></h2> <p>Γ¥î <strong>Over-parallelizing:</strong> More parallelism Γëá faster. Communication overhead can dominate.</p> <p>Γ¥î <strong>Ignoring hardware topology:</strong> Don’t use TP across nodes (slow interconnect).</p> <p>Γ¥î <strong>Skipping profiling:</strong> Measure before optimizing. Your intuition will be wrong.</p> <p>Γ¥î <strong>Cargo-culting configs:</strong> What works for LLaMA 70B won’t work for a video DiT.</p> <h2 id="next-steps"><a href="#next-steps">Next Steps</a></h2> <p><strong>Next Steps:</strong></p> <ul><li><strong>Long-Context Parallelism:</strong> Deep dive into SP/CP for 1M+ token contexts</li> <li><strong>Inference Serving:</strong> Apply parallelism thinking to latency-constrained serving</li></ul> <h2 id="maintenance"><a href="#maintenance">Maintenance</a></h2> <p>This is a <strong>living document.</strong> As you encounter new bottlenecks or discover better heuristics, update this page with:</p> <ul><li>Empirical throughput numbers</li> <li>Hardware-specific tuning</li> <li>Model-specific quirks (e.g., DiT vs Transformer parallelism)</li></ul><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="yggdrasil" scheme="https://https:///?tags=yggdrasil" />
    <category term="systems-hpc" scheme="https://https:///?tags=systems-hpc" />
    <category term="5D-parallelism" scheme="https://https:///?tags=5D-parallelism" />
    <category term="overlap" scheme="https://https:///?tags=overlap" />
    <category term="bucketing" scheme="https://https:///?tags=bucketing" />
    <category term="ZeRO" scheme="https://https:///?tags=ZeRO" />
    <category term="playbook" scheme="https://https:///?tags=playbook" />
    <category term="ultra-scale" scheme="https://https:///?tags=ultra-scale" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Some software I've been working on and other updates]]></title>
    <link href="https://https:///nov-25-updates" />
    <id>https://https:///nov-25-updates</id>
    <published>2025-11-04T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <summary type="html"><![CDATA[A summary of some software I've been working on, and other updates.]]></summary>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="astrophysics-libraries"><a href="#astrophysics-libraries">Astrophysics Libraries</a></h2> <p>I’ve been looking at some astrophysics libraries. For instance, I notice that radiative transfer line simulation grids are stored as uncompressed files, which means they take up a significant amount of space, rather than being compressed and being loadable from one file. This is true of <a href="https://github.com/saikumarmk/blueshifts" rel="nofollow noopener noreferrer external" target="_blank">saikumarmk/blueshifts</a>, a thesis repository for a paper that explores the changing spectral properties for a disc wind model. Additionally, SKIRTOR, a large collection of emission models of the dusty torus of an AGN has a large uncompressed collection, which I compressed at <a href="https://github.com/saikumarmk/skirtor" rel="nofollow noopener noreferrer external" target="_blank">saikumarmk/skirtor</a>, along with a recreation of the Streamlit application that lets you explore what different AGN look like under different parameters. In particular, the focus is on modelling the behaviour of the dusty torus in obscuring other spectral features.</p> <p>Kapteyn, a line fitting library for astronomy still uses an older version of <code>numpy&lt;2</code>, which makes it quite inconvenient for virtual environments. A quick glance reveals that the primary issues are due to changes in the <code>numpy</code> C API, and can simply be renamed, which my fork does - <a href="https://github.com/saikumarmk/kapteyn_fork" rel="nofollow noopener noreferrer external" target="_blank">saikumarmk/kapteyn_fork</a>.</p> <h2 id="pokemon-red-elo"><a href="#pokemon-red-elo">Pokemon Red Elo</a></h2> <p>Mostly refactors with code here. Though I would like to eventually try doing the same for Pokemon Crystal, which has a layered trainer AI system and it would make sense for parity.</p> <h1 id="the-handbook-scraper"><a href="#the-handbook-scraper">The Handbook Scraper</a></h1> <p>The scraper is still in an interesting state where the data is now there, but because the handbook formatting for some courses is strange, you can’t really use it for something such as course planning. Nonetheless, I suspect for courses, a pass with a model like Gemini will get you proper data.</p> <h2 id="a-transit-map-of-melbourne"><a href="#a-transit-map-of-melbourne">A Transit Map of Melbourne</a></h2> <p>My old project, <code>MiniMelbourne</code> finally got a face lift and a deploy to <a href="https://transit.saikumarmk.com" rel="nofollow noopener noreferrer external" target="_blank">transit.saikumarmk.com</a>. Check it! The PTV GTFS-R API also has bus, tram, and VLine API in addition to train data, so the map looks a fair bit more complete. It’s heavily inspired by <a href="https://minitokyo3d.com" rel="nofollow noopener noreferrer external" target="_blank">minitokyo3d</a>, which is a 3D map of Tokyo. You can find the source code here <a href="https://github.com/saikumarmk/mini-melbourne-3d" rel="nofollow noopener noreferrer external" target="_blank">saikumarmk/mini-melbourne-3d</a>.</p> <h2 id="this-site"><a href="#this-site">This Site</a></h2> <p>In case you haven’t noticed, a complete touch up has been done on the landing page for the site, along with a new portfolio view. It should also be a little less glitchy, and look cooler overall.</p> <h2 id="team-changes-at-canva"><a href="#team-changes-at-canva">Team changes at Canva</a></h2> <p>I’ve gone from Photo to Video, and our goal is to build a kick-ass video editor. The general theme we’re going for is using AI to assist with the creation of videos, but ultimately the user still controls what they want to put into a video.</p><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="software" scheme="https://https:///?tags=software" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Elements of this Website]]></title>
    <link href="https://https:///cool-stuff" />
    <id>https://https:///cool-stuff</id>
    <published>2025-07-14T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.251Z</updated>
    <summary type="html"><![CDATA[Kitchen sink for this site: nav map, search, themes, Mermaid, PythonCode, SlabTitle, Poké sprites, math, and slide layout demos—article or fullscreen deck.]]></summary>
    <content type="html">
      <![CDATA[<!--[0--><!--[0--><!--[0--><a href="/cool-stuff" class="slide-deck-present-btn btn btn-primary btn-sm gap-2"><span class="i-heroicons-outline-presentation-chart-bar w-4 h-4"></span> Present Slides</a><!--]--> <div class="slide-deck-viewport"><section data-slide="0" class="slide"><h1 id="this-site-in-one-deck"><a href="#this-site-in-one-deck">This site in one deck</a></h1> <p><strong>Article</strong> at this URL · <strong>present</strong> with <a href="/cool-stuff/deck/"><strong>Present Slides</strong> on this page</a> (or the button above) for fullscreen. <strong>Mermaid</strong>, <strong>PythonCode</strong>, <strong>SlabTitle</strong>, and <strong>PokemonSprite</strong> come from <code>post_layout.svelte</code> (mdsvex layout exports)—works in <strong>split slides</strong> and <strong>SSR</strong>.</p></section> <section data-slide="1" class="slide"><h2 id="quick-links"><a href="#quick-links">Quick links</a></h2> <ul><li><strong><a href="/portfolio">Portfolio</a></strong> · <strong><a href="/archive">Archive</a></strong> · <strong><a href="/playbook">Playbook</a></strong> · <strong><a href="/about">About</a></strong></li> <li><strong>Project Dex</strong> — <a href="/portfolio/projects"><code>/portfolio/projects</code></a> · <strong>Yggdrasil 2026</strong> — <a href="/growth/2026"><code>/growth/2026</code></a></li></ul></section> <section data-slide="2" class="slide"><h2 id="navigation--main-pages"><a href="#navigation--main-pages">Navigation &amp; main pages</a></h2> <ul><li><strong>About</strong> — <a href="/about"><code>/about</code></a></li> <li><strong>Portfolio</strong> — <a href="/portfolio"><code>/portfolio</code></a> · <strong>Project Dex</strong> — <a href="/portfolio/projects"><code>/portfolio/projects</code></a></li> <li><strong>Archive</strong> — <a href="/archive"><code>/archive</code></a> (all posts)</li> <li><strong>Playbook</strong> — <a href="/playbook"><code>/playbook</code></a> → FAQ, timeline, résumé, interviews (<code>guide-to-tech-*</code>)</li> <li><strong>Documents</strong> (header) — résumé PDF, thesis</li> <li><strong>Monash handbook graph</strong> — external link in the nav</li></ul></section> <section data-slide="3" class="slide"><h2 id="features"><a href="#features">Features</a></h2> <ul><li><strong>⌘K / Ctrl+K</strong> — full-text search (posts + static pages)</li> <li><strong>Theme</strong> — palette picker in the header (DaisyUI)</li> <li><strong>Atom</strong> / <strong>Sitemap</strong> — footer</li> <li><strong>Slides</strong> — <code>slides: true</code> in frontmatter + <strong>Present Slides</strong> or <a href="/cool-stuff/deck/"><code>/cool-stuff/deck/</code></a> for deck mode (this page)</li></ul></section> <section data-slide="4" class="slide"><h2 id="diagrams--code-embeds"><a href="#diagrams--code-embeds">Diagrams &amp; code embeds</a></h2> <!--[-1--><h1 class="flex flex-wrap items-baseline gap-x-3 gap-y-1 justify-center"><!--[--><span class="leading-none uppercase text-accent svelte-1c4a6un font-mono">Diagrams</span><span class="leading-none uppercase text-base-content svelte-1c4a6un font-mono">&amp;</span><span class="leading-none uppercase text-primary svelte-1c4a6un font-mono">code</span><!--]--></h1><!--]--><!----> <div class="not-prose max-w-full overflow-hidden"><div class="mermaid flex justify-center svelte-1bw883z"></div><!----></div> <div class="mermaid flex justify-center svelte-1bw883z"></div><!----> <div class="not-prose slide-code-focus"><div class="annotated-code not-prose svelte-1cwmi07"><h2 class="renderer-title svelte-1cwmi07">PonderNet (annotated Python)</h2> <div class="renderer-container svelte-1cwmi07"><!--[0--><div class="loading-state svelte-1cwmi07">Loading content...</div><!--]--></div></div><!----></div></section> <section data-slide="5" class="slide"><h2 id="sprites-layout-component"><a href="#sprites-layout-component">Sprites (layout component)</a></h2> <p><strong>PokemonSprite</strong> uses the same mdsvex layout mapping as Mermaid—no per-file <code>&lt;script></code> import.</p> <div class="not-prose flex flex-wrap items-end gap-8"><div class="flex flex-col items-center gap-2"><!--[-1--><div class="sprite-wrapper pokemon-sprite"><span class="pokesprite pokemon pikachu"></span></div><!--]--><!----> <span class="text-sm opacity-70">Block</span></div> <div class="flex flex-col gap-2"><p class="text-sm opacity-90">Inline next to text: <!--[0--><span class="sprite-wrapper pokemon-sprite inline-block align-middle ml-2"><span class="pokesprite pokemon eevee"></span></span><!--]--><!----></p></div></div></section> <section data-slide="6" class="slide"><h2 id="math-and-prose"><a href="#math-and-prose">Math and prose</a></h2> <p>Inline: <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>e</mi><mrow><mi>i</mi><mi>π</mi></mrow></msup><mo>+</mo><mn>1</mn><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">e^{i\pi} + 1 = 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">iπ</span></span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span>.</p> <p>Display:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="normal">∇</mi><mo>⋅</mo><mi mathvariant="bold">E</mi><mo>=</mo><mfrac><mi>ρ</mi><msub><mi>ε</mi><mn>0</mn></msub></mfrac></mrow><annotation encoding="application/x-tex">\nabla \cdot \mathbf{E} = \frac{\rho}{\varepsilon_0}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∇</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbf">E</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord"><span class="mord mathnormal">ε</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">ρ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span><!----></div></section> <section data-slide="7" class="slide"><h2 id="code-heavy-slide"><a href="#code-heavy-slide">Code-heavy slide</a></h2> <!----><pre class="shiki monokai" python="true"><div class="language-id">python</div><div class='code-container'><code><div class='line'>def hello():</div><div class='line'>    return "minimal · code-first"</div></code></div></pre><!----> <p>Use class <code>slide-code-focus</code> on a wrapper for tighter code slides (theme CSS).</p></section> <section data-slide="8" class="slide"><h2 id="two-columns-html"><a href="#two-columns-html">Two columns (HTML)</a></h2> <div class="slide-two-col not-prose"><div><h3 id="left"><a href="#left">Left</a></h3> <p>Bullet one<br/> Bullet two</p></div> <div><h3 id="right"><a href="#right">Right</a></h3> <p>More content here.</p></div></div></section> <section data-slide="9" class="slide"><h2 id="stagger-utility"><a href="#stagger-utility">Stagger utility</a></h2> <p>Apply classes <code>stagger-1</code> … <code>stagger-6</code> to block elements for delayed fade (see <code>slide-theme.css</code>).</p> <p class="stagger-1 opacity-90">First point</p> <p class="stagger-2 opacity-90">Second point</p></section> <section data-slide="10" class="slide"><h2 id="full-bleed"><a href="#full-bleed">Full bleed</a></h2> <p>Wrap content in <code>class="slide-full-bleed"</code> for edge-to-edge (theme variable <code>--slide-bleed</code>).</p></section> <section data-slide="11" class="slide"><h2 id="next-steps"><a href="#next-steps">Next steps</a></h2> <ul><li><strong>Browse</strong> <a href="/portfolio">Portfolio</a> and <a href="/archive">Archive</a></li> <li><strong>Search</strong> with ⌘K — try company names, tags, or post titles</li> <li><strong>Deck mode</strong>: use <strong>Present Slides</strong>, or open <a href="/cool-stuff/deck/"><code>/cool-stuff/deck/</code></a> for fullscreen slides</li></ul></section><!----><!----> <!--[-1--><!--]--></div><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="random" scheme="https://https:///?tags=random" />
    <category term="web-dev" scheme="https://https:///?tags=web-dev" />
    <category term="slides" scheme="https://https:///?tags=slides" />
    <category term="meta" scheme="https://https:///?tags=meta" />
  </entry>
  <entry>
    <title type="html"><![CDATA[More Pokemon Red Elo World]]></title>
    <link href="https://https:///pokered-elo-2" />
    <id>https://https:///pokered-elo-2</id>
    <published>2025-07-14T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <summary type="html"><![CDATA[An explanation on Elo]]></summary>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><p>So, I decided to revisit my Pokemon Red Elo estimation work, and decided to write this article up as a test for some of my new rendering capabilities. This article will primarily go over deriving Elo.</p> <h2 id="deriving-elo"><a href="#deriving-elo">Deriving Elo</a></h2> <p>Elo ratings are typically used in tournaments between players/teams, such as chess. It’s well known thatif a player with a lower Elo defeats a player with a higher Elo, the increase/decrease for the player is larger thansay if they were comparable in ‘skill’. The Elo rating is a measure of that skill. Let’s derive it. Suppose we have a ratings vector <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi><mo>=</mo><mo stretchy="false">(</mo><msub><mi>R</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>R</mi><mn>2</mn></msub><mo separator="true">,</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo separator="true">,</mo><msub><mi>R</mi><mi>n</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\theta = (R_1, R_2, ..., R_n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">θ</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">...</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span>, then our goal is to learn this vector.</p> <p><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">P_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">P_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> battle with ratings <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>R</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">R_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>R</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">R_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>. Then we define the Elo update for <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">P_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">P_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> as:</p> <p><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>R</mi><mn>1</mn><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup><mo>:</mo><mo>=</mo><msub><mi>R</mi><mn>1</mn></msub><mo>+</mo><mi>α</mi><mo stretchy="false">(</mo><mtext>Outcome</mtext><mo stretchy="false">(</mo><msub><mi>P</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>P</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>−</mo><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><msub><mi>P</mi><mn>1</mn></msub><mo>≻</mo><msub><mi>P</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">R_1&#x27; := R_1 + \alpha (\text{Outcome}(P_1,P_2)- \mathbb{P}(P_1\succ P_2)))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">:=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">α</span><span class="mopen">(</span><span class="mord text"><span class="mord">Outcome</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbb">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">≻</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)))</span></span></span></span><!----></span></p> <p><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>R</mi><mn>2</mn><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup><mo>:</mo><mo>=</mo><msub><mi>R</mi><mn>2</mn></msub><mo>+</mo><mi>α</mi><mo stretchy="false">(</mo><mtext>Outcome</mtext><mo stretchy="false">(</mo><msub><mi>P</mi><mn>2</mn></msub><mo separator="true">,</mo><msub><mi>P</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>−</mo><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><msub><mi>P</mi><mn>2</mn></msub><mo>≻</mo><msub><mi>P</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">R_2&#x27; := R_2 + \alpha (\text{Outcome}(P_2,P_1)- \mathbb{P}(P_2\succ P_1)))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">:=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">α</span><span class="mopen">(</span><span class="mord text"><span class="mord">Outcome</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbb">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">≻</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)))</span></span></span></span><!----></span></p> <ul><li>Here <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>≻</mo><mi>B</mi></mrow><annotation encoding="application/x-tex">A \succ B</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">A</span><span class="mspace"></span><span class="mrel">≻</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">B</span></span></span></span><!----></span> means A dominates (beats) B</li> <li>Where <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext>Outcome</mtext><mo stretchy="false">(</mo><msub><mi>P</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>P</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\text{Outcome}(P_1,P_2)=1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord text"><span class="mord">Outcome</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> if <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">P_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>, and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn></mrow><annotation encoding="application/x-tex">0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span> if <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">P_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> wins.</li> <li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">α</span></span></span></span><!----></span> is the scale factor, or how impactful a loss is.</li></ul> <p>Note if it’s a tie, then it’s considered both a loss and win for simplicity. If <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">P_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> was an underdog, say Youngster Joey, taking on E4 Agatha, then the probability of him beating her would be muchlower, and thus his Elo would go up quite a bit. On the other hand, it would be expected of Agatha to beat Joey, so the Elo increment is miniscule in comparison.</p> <p>But what is <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><msub><mi>P</mi><mn>1</mn></msub><mo>≻</mo><msub><mi>P</mi><mn>2</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathbb{P}(P_1\succ P_2)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbb">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">≻</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span>? We want the odds of <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">P_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> beating <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">P_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> to be a function of <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>R</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">R_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>R</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">R_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>, that is there is some <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span></span></span></span><!----></span> such that:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mfrac><mrow><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><msub><mi>P</mi><mn>1</mn></msub><mo>≻</mo><msub><mi>P</mi><mn>2</mn></msub><mo stretchy="false">)</mo></mrow><mrow><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><msub><mi>P</mi><mn>2</mn></msub><mo>≻</mo><msub><mi>P</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow></mfrac><mo>=</mo><mfrac><mrow><mi>f</mi><mo stretchy="false">(</mo><msub><mi>R</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow><mrow><mi>f</mi><mo stretchy="false">(</mo><msub><mi>R</mi><mn>2</mn></msub><mo stretchy="false">)</mo></mrow></mfrac><mo>=</mo><msub><mi>O</mi><mrow><msub><mi>P</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>P</mi><mn>2</mn></msub></mrow></msub></mrow><annotation encoding="application/x-tex">\frac{\mathbb{P}(P_1\succ P_2)}{\mathbb{P}(P_2 \succ P_1)} = \frac{f(R_1)}{f(R_2)} = O_{P_1, P_2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathbb">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">≻</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord mathbb">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">≻</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">O</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><!----></div> <p>And that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><msub><mi>P</mi><mn>1</mn></msub><mo>≻</mo><msub><mi>P</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>+</mo><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><msub><mi>P</mi><mn>2</mn></msub><mo>≻</mo><msub><mi>P</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\mathbb{P}(P_1\succ P_2) + \mathbb{P}(P_2 \succ P_1) = 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbb">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">≻</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbb">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">≻</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span>. We can disregard ties for the moment since they’re not a substantial issue here.</p> <p>Because the probabilities add to <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn></mrow><annotation encoding="application/x-tex">1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span>, we have <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>O</mi><mrow><msub><mi>P</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>P</mi><mn>2</mn></msub></mrow></msub><mo>+</mo><mn>1</mn><mo>=</mo><mfrac><mn>1</mn><mrow><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><msub><mi>P</mi><mn>2</mn></msub><mo>≻</mo><msub><mi>P</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow></mfrac></mrow><annotation encoding="application/x-tex">O_{P_1, P_2} + 1 = \frac{1}{\mathbb{P}(P_2 \succ P_1)}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">O</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathbb mtight">P</span><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mrel mtight">≻</span><span class="mord mtight"><span class="mord mathnormal mtight">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose mtight">)</span></span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span><!----></span> yielding:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mfrac><msub><mi>O</mi><mrow><msub><mi>P</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>P</mi><mn>2</mn></msub></mrow></msub><mrow><msub><mi>O</mi><mrow><msub><mi>P</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>P</mi><mn>2</mn></msub></mrow></msub><mo>+</mo><mn>1</mn></mrow></mfrac><mo>=</mo><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><msub><mi>P</mi><mn>1</mn></msub><mo>≻</mo><msub><mi>P</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mfrac><mrow><mi>f</mi><mo stretchy="false">(</mo><msub><mi>R</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow><mrow><mi>f</mi><mo stretchy="false">(</mo><msub><mi>R</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>+</mo><mi>f</mi><mo stretchy="false">(</mo><msub><mi>R</mi><mn>2</mn></msub><mo stretchy="false">)</mo></mrow></mfrac></mrow><annotation encoding="application/x-tex">\frac{O_{P_1, P_2}}{O_{P_1, P_2}+1} = \mathbb{P}(P_1\succ P_2) = \frac{f(R_1)}{f(R_1)+f(R_2)}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord"><span class="mord mathnormal">O</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span><span class="mord">1</span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord"><span class="mord mathnormal">O</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbb">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">≻</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span><!----></div> <p>Now, what function reasonably satisfies this? The simplest answer is an exponential of the form <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><mo stretchy="false">(</mo><mi>R</mi><mo stretchy="false">)</mo><mo>=</mo><mi>exp</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>k</mi><mi>R</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f:(R) = \exp(k R)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mspace"></span><span class="mrel">:</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord mathnormal">R</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop">exp</span><span class="mopen">(</span><span class="mord mathnormal">k</span><span class="mord mathnormal">R</span><span class="mclose">)</span></span></span></span><!----></span>, which when substituted yields:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable width="100%"><mtr><mtd width="50%"></mtd><mtd><mrow><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><msub><mi>P</mi><mn>1</mn></msub><mo>≻</mo><msub><mi>P</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mfrac><mn>1</mn><mrow><mn>1</mn><mo>+</mo><mi>exp</mi><mo>⁡</mo><mo stretchy="false">(</mo><mo>−</mo><mi>k</mi><mo stretchy="false">(</mo><msub><mi>R</mi><mn>1</mn></msub><mo>−</mo><msub><mi>R</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow></mfrac></mrow></mtd><mtd width="50%"></mtd><mtd><mtext>(1)</mtext></mtd></mtr></mtable><annotation encoding="application/x-tex">\mathbb{P}(P_1\succ P_2) = \frac{1}{1+\exp(-k(R_1-R_2))}  \tag{1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbb">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">≻</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord">1</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span><span class="mop">exp</span><span class="mopen">(</span><span class="mord">−</span><span class="mord mathnormal">k</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">))</span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span></span><span class="tag"><span class="strut"></span><span class="mord text"><span class="mord">(</span><span class="mord"><span class="mord">1</span></span><span class="mord">)</span></span></span></span></span></span><!----></div> <p>The choice of base and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span></span></span></span><!----></span> determines how much a win means at a certain odds ratio, and aren’t really too important. This is essentially a sigmoid <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">σ</span></span></span></span><!----></span> as well. Now, let’s say we have our data from the tournament, which could look something like the following:</p> <!----><pre class="shiki monokai"><div class='code-container'><code><div class='line'>win, trainer_1, trainer_2</div><div class='line'>1, AGATHA, YOUNGSTER</div><div class='line'>0, GREEN1, LANCE</div><div class='line'>...</div></code></div></pre><!----> <p>Here, <code>trainer_1</code> is the defender and <code>trainer_2</code> is the contender, meaning that the <code>win</code> is whether the defender won or not. But this data sounds like it would come from something that’s like a Bernoulli distribution! It so happensthat this formulation is a GLM with the <a href="https://en.wikipedia.org/wiki/Generalized_linear_model" rel="nofollow noopener noreferrer external" target="_blank">Logit link</a>, which is what we commonly call the Logistic Regression. So, our data <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">D</mi><mo>=</mo><mo stretchy="false">{</mo><mo stretchy="false">(</mo><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo separator="true">,</mo><msup><mi>y</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo stretchy="false">)</mo><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\mathcal{D} = \{(x^{(i)}, y^{(i)})\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathcal">D</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">{(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mclose">)}</span></span></span></span><!----></span> consists of:</p> <ul><li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>y</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo>∈</mo><mo stretchy="false">{</mo><mn>0</mn><mo separator="true">,</mo><mn>1</mn><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">y^{(i)} \in \{0,1\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">{</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">1</span><span class="mclose">}</span></span></span></span><!----></span></li> <li><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>x</mi><mrow><mi>k</mi><mo separator="true">,</mo><mi>j</mi></mrow><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msubsup><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mn>391</mn></msup></mrow><annotation encoding="application/x-tex">x^{(i)}_{k,j} \in \mathbb{R}^{391}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">k</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">j</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">391</span></span></span></span></span></span></span></span></span></span></span></span><!----></span>, where the the vector is <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn></mrow><annotation encoding="application/x-tex">0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span> except for <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn></mrow><annotation encoding="application/x-tex">1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> in the kth entry and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">-1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">−</span><span class="mord">1</span></span></span></span><!----></span> in the jth entry</li></ul> <p>Well, we know from equation <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span><!----></span>, what a good way of modelling the probability is. Via the PDF for the Bernoulli distribution, the probability of battle <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup></mrow><annotation encoding="application/x-tex">x^{(i)}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span></span></span></span><!----></span> resulting in outcome <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>y</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">y_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span> is:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable width="100%"><mtr><mtd width="50%"></mtd><mtd><mrow><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><msup><mi>y</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo>=</mo><msub><mi>y</mi><mi>i</mi></msub><mi mathvariant="normal">∣</mi><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo separator="true">;</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><mi>σ</mi><mo stretchy="false">(</mo><msup><mi>θ</mi><mi>T</mi></msup><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><msup><mo stretchy="false">)</mo><msup><mi>y</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup></msup><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mi>σ</mi><mo stretchy="false">(</mo><msup><mi>θ</mi><mi>T</mi></msup><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo stretchy="false">)</mo><msup><mo stretchy="false">)</mo><mrow><mn>1</mn><mo>−</mo><msup><mi>y</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup></mrow></msup></mrow></mtd><mtd width="50%"></mtd><mtd><mtext>(Likelihood of a datapoint)</mtext></mtd></mtr></mtable><annotation encoding="application/x-tex">\mathbb{P}(y^{(i)}=y_i | x^{(i)}; \theta) = \sigma(\theta^T x^{(i)})^{y^{(i)}} (1-\sigma(\theta^T x^{(i)}))^{1-y^{(i)}} \tag{Likelihood of a datapoint}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathbb">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace"></span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">σ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">θ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">T</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">σ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">θ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">T</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="tag"><span class="strut"></span><span class="mord text"><span class="mord">(</span><span class="mord"><span class="mord">Likelihood of a datapoint</span></span><span class="mord">)</span></span></span></span></span></span><!----></div> <p>Recalling that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>θ</mi><mi>T</mi></msup><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo>=</mo><msub><mi>R</mi><mi>k</mi></msub><mo>−</mo><msub><mi>R</mi><mi>j</mi></msub></mrow><annotation encoding="application/x-tex">\theta^T x^{(i)} = R_k - R_j</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">θ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">T</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>. How do we determine <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi></mrow><annotation encoding="application/x-tex">\theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">θ</span></span></span></span><!----></span>? This is a classic Logistic problem, with <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">L</mi><mo stretchy="false">(</mo><mi mathvariant="script">D</mi><mo separator="true">,</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><msubsup><mo>∏</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>N</mi></msubsup><mi mathvariant="double-struck">P</mi><mo stretchy="false">(</mo><mi>y</mi><mo>=</mo><msup><mi>y</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mi mathvariant="normal">∣</mi><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo separator="true">;</mo><mi>θ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathcal{L}(\mathcal{D},\theta) = \prod_{i=1}^N \mathbb{P}(y=y^{(i)} | x^{(i)}; \theta)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathcal">L</span><span class="mopen">(</span><span class="mord mathcal">D</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop"><span class="mop op-symbol small-op">∏</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">N</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mord mathbb">P</span><span class="mopen">(</span><span class="mord mathnormal">y</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace"></span><span class="mord mathnormal">θ</span><span class="mclose">)</span></span></span></span><!----></span>, which we want to maximise, or alternatively minimise <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">J</mi><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><mo>−</mo><mi>log</mi><mo>⁡</mo><mi mathvariant="script">L</mi><mo stretchy="false">(</mo><mi mathvariant="script">D</mi><mo separator="true">,</mo><mi>θ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathcal{J}(\theta) = - \log \mathcal{L}(\mathcal{D},\theta)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathcal">J</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">−</span><span class="mspace"></span><span class="mop">log</span><span class="mspace"></span><span class="mord mathcal">L</span><span class="mopen">(</span><span class="mord mathcal">D</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">θ</span><span class="mclose">)</span></span></span></span><!----></span>.</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable rowspacing="0.25em" columnalign="right left" columnspacing="0em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mi mathvariant="script">J</mi><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mo>−</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>N</mi></munderover><mrow><mo fence="true">(</mo><mi>log</mi><mo>⁡</mo><mrow><mo fence="true">(</mo><mi>σ</mi><mo stretchy="false">(</mo><msup><mi>θ</mi><mi>T</mi></msup><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><msup><mo stretchy="false">)</mo><msup><mi>y</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup></msup><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mi>σ</mi><mo stretchy="false">(</mo><msup><mi>θ</mi><mi>T</mi></msup><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo stretchy="false">)</mo><msup><mo stretchy="false">)</mo><mrow><mn>1</mn><mo>−</mo><msup><mi>y</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup></mrow></msup><mo fence="true">)</mo></mrow><mo fence="true">)</mo></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mo>−</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>N</mi></munderover><mrow><mo fence="true">(</mo><msup><mi>y</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mi>log</mi><mo>⁡</mo><mi>σ</mi><mo stretchy="false">(</mo><msup><mi>w</mi><mi>T</mi></msup><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo stretchy="false">)</mo><mo>+</mo><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><msup><mi>y</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo stretchy="false">)</mo><mi>log</mi><mo>⁡</mo><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mi>σ</mi><mo stretchy="false">(</mo><msup><mi>w</mi><mi>T</mi></msup><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo fence="true">)</mo></mrow></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">\begin{align*}\mathcal{J}(\theta) &amp;= -\sum_{i=1}^N \left(\log \left( \sigma(\theta^T x^{(i)})^{y^{(i)}} (1-\sigma(\theta^T x^{(i)}))^{1-y^{(i)}}\right) \right)  \\ &amp;=-\sum_{i=1}^N \left( y^{(i)} \log \sigma(w^T x^{(i)} ) + (1-y^{(i)}) \log (1 - \sigma(w^T x^{(i)}))  \right)\end{align*}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathcal">J</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span></span></span><span class="pstrut"><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord"></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span><span class="mord">−</span><span class="mspace"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">N</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size2">(</span></span><span class="mop">log</span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size2">(</span></span><span class="mord mathnormal">σ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">θ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">T</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord mathnormal">σ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">θ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">T</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mclose delimcenter"><span class="delimsizing size2">)</span></span></span><span class="mclose delimcenter"><span class="delimsizing size2">)</span></span></span></span></span><span class="pstrut"><span class="mord"><span class="mord"></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span><span class="mord">−</span><span class="mspace"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">N</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size2">(</span></span><span class="mord"><span class="mord mathnormal">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">σ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">w</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">T</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mop">log</span><span class="mopen">(</span><span class="mord">1</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord mathnormal">σ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">w</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">T</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mclose">))</span><span class="mclose delimcenter"><span class="delimsizing size2">)</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span></span></span><!----></div> <p>To compute <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∇</mi><mi mathvariant="script">J</mi><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\nabla \mathcal{J}(\theta)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∇</span><span class="mord mathcal">J</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span></span></span></span><!----></span>, we note that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="normal">∂</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><mi>σ</mi><mo stretchy="false">(</mo><msup><mi>θ</mi><mi>T</mi></msup><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>=</mo><mi>σ</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mi>σ</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><msup><mi>x</mi><mi>T</mi></msup></mrow><annotation encoding="application/x-tex">\partial_{\theta} (\sigma(\theta^T x)) = \sigma(x)(1-\sigma(x)) x^T</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord">∂</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">θ</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">σ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">θ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">T</span></span></span></span></span></span></span></span><span class="mord mathnormal">x</span><span class="mclose">))</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">σ</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mopen">(</span><span class="mord">1</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">σ</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">))</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">T</span></span></span></span></span></span></span></span></span></span></span><!----></span> via the chain rule and find that:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable width="100%"><mtr><mtd width="50%"></mtd><mtd><mrow><mi mathvariant="normal">∇</mi><mi mathvariant="script">J</mi><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><mo>−</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>N</mi></munderover><mrow><mo fence="true">(</mo><mi>σ</mi><mo stretchy="false">(</mo><msup><mi>w</mi><mi>T</mi></msup><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo stretchy="false">)</mo><mo>−</mo><msup><mi>y</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup><mo fence="true">)</mo></mrow><msup><mi>x</mi><mrow><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo></mrow></msup></mrow></mtd><mtd width="50%"></mtd><mtd><mtext>(Gradient of NLL)</mtext></mtd></mtr></mtable><annotation encoding="application/x-tex">\nabla \mathcal{J}(\theta) = -\sum_{i=1}^N \left(\sigma(w^T x^{(i)}) - y^{(i)} \right) x^{(i)} \tag{Gradient of NLL}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∇</span><span class="mord mathcal">J</span><span class="mopen">(</span><span class="mord mathnormal">θ</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">−</span><span class="mspace"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">N</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size2">(</span></span><span class="mord mathnormal">σ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">w</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">T</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mclose delimcenter"><span class="delimsizing size2">)</span></span></span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span></span><span class="tag"><span class="strut"></span><span class="mord text"><span class="mord">(</span><span class="mord"><span class="mord">Gradient of NLL</span></span><span class="mord">)</span></span></span></span></span></span><!----></div> <p>There’s no closed form solution for this, due to <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>y</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">y_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>, so we have to rely on Gradient Descent and company to approximate our rankings. The most basic update that you’d know is that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>θ</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn></mrow></msub><mo>=</mo><msub><mi>θ</mi><mi>i</mi></msub><mo>−</mo><mi>η</mi><mi mathvariant="normal">∇</mi><mi mathvariant="script">J</mi><mo stretchy="false">(</mo><msub><mi>θ</mi><mi>i</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\theta_{i+1} = \theta_{i} - \eta \nabla \mathcal{J}(\theta_i)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">θ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">θ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">η</span><span class="mord">∇</span><span class="mord mathcal">J</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">θ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span>, where <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>η</mi></mrow><annotation encoding="application/x-tex">\eta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">η</span></span></span></span><!----></span> is the learning rate. Since our problem is reasonably small, we don’t really need to worry about providing a mini-batch of <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span></span></span></span><!----></span> terms as our gradient. Though I will add that you can do an ‘online’ update where new matches provide gradient updates, and slowly update our rankings if needed, which is a cool connection. We could also contextualise momentum (e.g Adam) as smoothing our gradient from previous gradients as well.</p> <p>Let’s look through the annotated code now!</p> <div class="annotated-code not-prose svelte-1cwmi07"><h2 class="renderer-title svelte-1cwmi07"></h2> <div class="renderer-container svelte-1cwmi07"><!--[0--><div class="loading-state svelte-1cwmi07">Loading content...</div><!--]--></div></div><!----><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="pokemon" scheme="https://https:///?tags=pokemon" />
    <category term="simulation" scheme="https://https:///?tags=simulation" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Approximating pimanrules Pokemon Red Elo World]]></title>
    <link href="https://https:///pokered-elo-1" />
    <id>https://https:///pokered-elo-1</id>
    <published>2024-12-15T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <summary type="html"><![CDATA[A brief introduction to pkmn/engine]]></summary>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><p>In case it’s not already clear to the reader, I love Pokemon. Part of my obsession with Pokemon included simulating the trainer AI from the older games. pimanrules has a series of videos which simulate all <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>∼</mo><msup><mn>391</mn><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">\sim 391^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mrel">∼</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">39</span><span class="mord"><span class="mord">1</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><!----></span> possible trainer AI battles in <a href="https://www.youtube.com/watch?v=8yUPhRJtNJM" rel="nofollow noopener noreferrer external" target="_blank">Pokemon Red</a>, <a href="https://www.youtube.com/watch?v=247qD1qulSQ" rel="nofollow noopener noreferrer external" target="_blank">equalising all trainer levels to level 50</a>, and running the same tournament for <a href="https://www.youtube.com/watch?v=Q6E6OaWb7LQ" rel="nofollow noopener noreferrer external" target="_blank">Pokemon Crystal</a>. The simulation is done directly via a Gameboy emulator, with the memory addresses swapped to make battle decisions. That means the hours required to simulate all the battles come to around 192 hours. My goal was to see if I could achieve this speed-up. Battling is the heart of Pokemon, and being able to analyse the trials set before the player is a very interesting way to to look at the way the games were design for players. In the end, I cut down the simulation time for all <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>391</mn><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">391^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">39</span><span class="mord"><span class="mord">1</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><!----></span> battles in Pokemon Red from 192 hours (computing hours) to <strong>two and a half minutes</strong>. The GitHub project can be found at <a href="https://github.com/saikumarmk/pokered-trainer-tournament" rel="nofollow noopener noreferrer external" target="_blank">saikumarmk/pokered-trainer-tournament</a>, and the necessary bindings are available at <a href="https://github.com/saikumarmk/PyKMN/" rel="nofollow noopener noreferrer external" target="_blank">saikumarmk/PyKMN</a>.</p> <p>My journey began years ago, with the <a href="https://github.com/pret/pokered" rel="nofollow noopener noreferrer external" target="_blank">pokered</a> dissassembly project. The first idea that came to mind would be simulating the <a href="https://github.com/pret/pokered/blob/master/engine/battle/core.asm" rel="nofollow noopener noreferrer external" target="_blank">core</a> battle system by implementing a rudimentary ASM interpreter, however, I realised that the complexity of the project would shoot up because I’d need to go from ASM to some higher level language.</p> <p>This idea stagnated till I had a rewatch of the video, and learned that the <a href="https://github.com/smogon/pokemon-showdown" rel="nofollow noopener noreferrer external" target="_blank">Pokemon Showdown</a> battle logic was available online. I immediately revisited the disassembly, since I knew if I could scrape the trainer and Pokemon data, all I’d have to do is recreate the trainer AI and then run all the battles.</p> <h2 id="pokemon-trainer-ai-tidbits"><a href="#pokemon-trainer-ai-tidbits">Pokemon Trainer AI tidbits</a></h2> <p>The generation one trainer AI is relatively straightforward, and can be found <a href="http://wiki.pokemonspeedruns.com/index.php/Pok%C3%A9mon_Red/Blue/Yellow_Trainer_AI" rel="nofollow noopener noreferrer external" target="_blank">here</a>. However, some trainers have custom AI modifiers, like the gym leaders and the elite four. More information can be found on this <a href="https://gamefaqs.gamespot.com/gameboy/367023-pokemon-red-version/faqs/64175/ai" rel="nofollow noopener noreferrer external" target="_blank">Gamefaqs guide</a>. In short, the three primary modifications for Pokemon RBY are:</p> <h3 id="modifier-1---dont-use-status-moves"><a href="#modifier-1---dont-use-status-moves">Modifier 1 - Don’t use status moves</a></h3> <p>If the enemy Pokemon has a status condition, discourage using a non-attacking status move. There’s a list of moves that fall under this.</p> <h3 id="modifier-2---buff-on-turn-one-two"><a href="#modifier-2---buff-on-turn-one-two">Modifier 2 - Buff on turn <del>one</del> two</a></h3> <p>If there’s a move that buffs your Pokemon, on the second turn, prioritise those moves. Because of an off-by-one error, this modifier really should be applied on the first turn.</p> <h3 id="modifier-3---use-supereffective-moves"><a href="#modifier-3---use-supereffective-moves">Modifier 3 - Use supereffective moves</a></h3> <p>If there’s a move that’s considered ‘super effective’ against the <strong>first</strong> type of enemy Pokemon, prioritise that. Additionally, check to see if the Pokemon can use any ‘alternative moves’ (moves with a special damage calculation <sup id="fnref-1"><a href="#fn-1" class="footnote-ref">1</a></sup>). If these moves are useable, then penalise using moves that are not very effective/ineffective. Note that there’s no damage check here, so you can get into situations such as Lorelei’s Dewgong spamming rest (which is patched in Yellow).</p> <p>In generation one, trainer Pokemon movesets are determined by the last four moves they learned from their level <sup id="fnref-2"><a href="#fn-2" class="footnote-ref">2</a></sup>.</p> <h2 id="the-pkmnengine"><a href="#the-pkmnengine">The pkmn/engine</a></h2> <p>While exploring the <a href="https://github.com/pkmn/ps" rel="nofollow noopener noreferrer external" target="_blank">different implementations of the Pokemon Showdown modules</a>, I found a project called <a href="https://github.com/pkmn/engine" rel="nofollow noopener noreferrer external" target="_blank">pkmn/engine</a>. The project is a minimal Pokemon battle simulation engine built in Zig, a modern successor to C and is touted as a minimal battle engine. Being compiled in Zig means that the simulation is 1000x faster than the Showdown battle simulation, which is desirable for us. It also intends to be as close to both the original game and Pokemon showdown. This was genuinely amazing when I found it, as it meant that I could use the <a href="https://github.com/AnnikaCodes/PyKMN" rel="nofollow noopener noreferrer external" target="_blank">Python bindings</a> and simulate all the battles with relative ease.</p> <h2 id="pykmn"><a href="#pykmn">PyKMN</a></h2> <p>PyKMN is the project that exposes the <code>engine</code> to Python. Unfortunately, the task was never going to be as straightforward as just compiling the bindings. My fork of PyKMN is available <a href="https://github.com/saikumarmk/PyKMN" rel="nofollow noopener noreferrer external" target="_blank">here</a> and you can use it to compile the necessary wheels to install <code>PyKMN</code> and use it with the <a href="https://github.com/saikumarmk/pokered-trainer-tournament" rel="nofollow noopener noreferrer external" target="_blank">pokered-trainer-tournament</a> project.</p> <p>Off the bat, the C headers didn’t compile because there was a static assertion that required removing. I wanted the bindings to be compatible with the latest version of the engine, so I made it target the master branch of <code>pkmn/engine</code>. I also needed to change <code>-Dtrace</code> to <code>-Dlog</code>, though I picked up on this relatively quickly as it complained that the argument was invalid.</p> <p>After that, I had to make some modifications to <code>pykmn/engine/gen1.py</code>. For the time being, I’ve set the engine to always enable tracing as it previously wasn’t picking up on the <code>HAS_TRACE</code> flag. The final modifications involved renaming some variables such as <code>disabled_duration</code> to <code>disable_duration</code> or <code>PKMN_OPTIONS_SIZE</code> to <code>PKMN_CHOICES_SIZE</code> which was accomplished by debugging a battle and inspecting the present variables. That made nearly all the tests pass, with the exception of a few oddities with the move disable, which causes a test case to fail as it wears off earlier than it should have. That was good enough for me anyway. This was a mildly irritating experience as I had to check the headers each time the FFI interface encountered an error, then potentially modify the headers and regenerate the wheel.</p> <h2 id="getting-relevant-trainer-data"><a href="#getting-relevant-trainer-data">Getting relevant trainer data</a></h2> <p>The relevant <code>asm</code> files from <code>pokered</code> include the:</p> <ul><li><code>base_stats</code> folder which contains their level one learnset</li> <li><code>dex.asm</code> which contains the Pokedex numbers of each Pokemon</li> <li><code>evos_moves.asm</code> contains the way each Pokemon evolves and its learnset</li> <li><code>move_choices.asm</code> contains the AI modifiers each trainer class has</li> <li><code>moves.asm</code> contains each move, any effects, its power, the type, accuracy and powerpoints</li> <li><code>parties.asm</code> contains the trainer Pokemon data for each trainer. Note that trainers with custom moves (Gym + E4) are in a separate file</li></ul> <p>There are a couple of Pokemon names such as Mr Mime, and Nidoran M/F that are also spelt inconsistently, so we added some extra processing for them. We parse these and then store them in a pickled format.</p> <h2 id="the-battle-engine"><a href="#the-battle-engine">The Battle Engine</a></h2> <p>At a high level, the battle engine is straightforward - You specify two teams and then update the state of the battle by selecting a valid choice. These valid choices consist of swapping Pokemon, choosing a move, or passing (when you cause an enemy Pokemon to faint).</p> <!----><pre class="shiki monokai" py="true"><div class="language-id">py</div><div class='code-container'><code><div class='line'>def run_battle(trainer1: Trainer, trainer2: Trainer, log=True) -&gt; ResultType:</div><div class='line'>    team1 = trainer1.pokemon</div><div class='line'>    team2 = trainer2.pokemon</div><div class='line'></div><div class='line'>    battle = Battle(</div><div class='line'>        p1_team=team1,</div><div class='line'>        p2_team=team2,</div><div class='line'>    )</div><div class='line'>    slots: Slots = Slots(([p.species for p in team1], [p.species for p in team2]))</div><div class='line'></div><div class='line'>    # Turn 0</div><div class='line'>    (result, trace) = battle.update(Choice.PASS(), Choice.PASS())</div><div class='line'>    choice = 1</div><div class='line'>    while result.type() == ResultType.NONE:</div><div class='line'>        choice += 1</div><div class='line'>        (result, trace) = advance_battle(battle, result, trainer1, trainer2)</div><div class='line'>        if choice &gt; 1000:  # any stalling = tie</div><div class='line'>            return ResultType.TIE</div><div class='line'></div><div class='line'>    return result.type(), choice</div></code></div></pre><!----> <p>The Pokemon data class allows you to specify the species, the moveset, and optionally, the level of the Pokemon.</p> <h2 id="putting-it-all-together"><a href="#putting-it-all-together">Putting it all together</a></h2> <p>We then pit each trainer against every other trainer. Originally, I had it so that each trainer would fight each other twice (one from the POV of P1 and one from the POV of P2) but left this out to see how close it could get to results from pimanrules’ video.</p> <p>Overall, the ELO ranking <sup id="fnref-3"><a href="#fn-3" class="footnote-ref">3</a></sup> looked something like this:</p> <!----><pre class="shiki monokai"><div class='code-container'><code><div class='line'>Trainer: Green1 - Green1-C, LR Elo: 216.54730776458132</div><div class='line'>Trainer: Green1 - Green1-B, LR Elo: 224.5904410299538</div><div class='line'>Trainer: Green1 - Green1-A, LR Elo: 263.5018156696094</div><div class='line'>Trainer: BugCatcher - Route 3-C, LR Elo: 484.2755546418754</div><div class='line'>Trainer: BugCatcher - Viridian Forest-C, LR Elo: 484.68162792183057</div><div class='line'>Trainer: BugCatcher - Viridian Forest-A, LR Elo: 485.53990646640864</div><div class='line'>Trainer: SuperNerd - Mt. Moon 1F-A, LR Elo: 486.99372378593375</div><div class='line'>Trainer: Green1 - Route 22-C, LR Elo: 487.50635955968653</div><div class='line'>Trainer: BugCatcher - Mt. Moon 1F-B, LR Elo: 527.9433109209984</div><div class='line'>Trainer: BugCatcher - Viridian Forest-B, LR Elo: 542.0513046912079</div><div class='line'>Trainer: BugCatcher - Route 3-B, LR Elo: 553.9063718053528</div><div class='line'>Trainer: Green1 - Route 22-A, LR Elo: 557.79961894872</div><div class='line'>Trainer: Lass - Route 3-C, LR Elo: 559.1822159583655</div><div class='line'>Trainer: BugCatcher - Mt. Moon 1F-A, LR Elo: 565.9331459744931</div><div class='line'>Trainer: Hiker - Rock Tunnel B1F-B, LR Elo: 595.3713903703574</div><div class='line'>...</div><div class='line'>...</div><div class='line'>Trainer: Green2 - Route 22-A, LR Elo: 2473.3390468334183</div><div class='line'>Trainer: Green3 - Green3-A, LR Elo: 2497.382132748259</div><div class='line'>Trainer: Green3 - Green3-C, LR Elo: 2527.5603417405864</div><div class='line'>Trainer: Juggler - Victory Road 2F-A, LR Elo: 2528.905720644544</div><div class='line'>Trainer: Green3 - Green3-B, LR Elo: 2533.134741771907</div><div class='line'>Trainer: ProfOak - Unused-C, LR Elo: 2675.2609434721703</div><div class='line'>Trainer: ProfOak - Unused-A, LR Elo: 2704.059987738582</div><div class='line'>Trainer: ProfOak - Unused-B, LR Elo: 2713.6055194321307</div></code></div></pre><!----> <p>So while not exactly the same in terms of results (due to some minor implementation details), we get pretty close.</p> <h2 id="conclusion---features-to-implement"><a href="#conclusion---features-to-implement">Conclusion - Features to implement</a></h2> <p>I have yet to implement trainer AI features such as using potions, switching out Pokemon, or Gym Leader AI which may bias the results. I would also like to make nice visualisations for this project, though it’s not nearly a top priority as pimanrules’ video does that already. It would be very cool to see how <code>pkmn/engine</code> develops, and whether we can recreate the same setup for Pokemon Crystal.</p> <!--[-1--><div class="sprite-wrapper medium"><span class="pokesprite pokemon alakazam"></span></div><!--]--><!----> <div class="footnotes"><hr/> <ol><li id="fn-1">Dragon Rage, Fly, Psywave, and Super Fang are some examples of these special damage moves.<a href="#fnref-1" class="footnote-backref">↩</a></li> <li id="fn-2">It’s a little more complicated than this - you can check the AI Pokemon move sets section of the <a href="https://gamefaqs.gamespot.com/gameboy/367023-pokemon-red-version/faqs/64175/ai" rel="nofollow noopener noreferrer external" target="_blank">Gamefaqs guide</a><a href="#fnref-2" class="footnote-backref">↩</a></li> <li id="fn-3">The ELO algorithm is the same as the Pokemon Red Redux tournament where linear regression is used to estimate the rankings of trainers.<a href="#fnref-3" class="footnote-backref">↩</a></li></ol></div><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="pokemon" scheme="https://https:///?tags=pokemon" />
    <category term="simulation" scheme="https://https:///?tags=simulation" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Prompting a Unit Score Dashboard with Claude]]></title>
    <link href="https://https:///unit-scores-dashboard" />
    <id>https://https:///unit-scores-dashboard</id>
    <published>2024-12-15T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><p>A couple of weeks ago, I wanted to test out Claude Sonnet’s capabilities for generating web applications, as my attention had been brought to <a href="https://bolt.new/" rel="nofollow noopener noreferrer external" target="_blank">bolt.new</a>, a prompt system that allows you to prompt full-stack web applications. Word on the street, according to people I work with was that Claude’s Sonnet was very powerful for generating entire applications, and I had yet to trial Sonnet on my personal account. I tested Sonnet’s capabilities by asking the model to replicate the heat map of <a href="https://www.saikumarmk.com/the-story-of-setool/" rel="nofollow noopener noreferrer external" target="_blank">SETool</a>, a now-defunct <sup id="fnref-1"><a href="#fn-1" class="footnote-ref">1</a></sup> piece of software that deploys a Dash application to Heroku for visualising unit outcomes.</p> <p>Introducing the <a href="https://saikumarmk.github.io/unit-scores-dashboard/" rel="nofollow noopener noreferrer external" target="_blank">Unit Scores Dashboard</a> for anyone at Monash who’s ever tried to make sense of the SETU outcomes for units, and used SETool in the past. I provided Claude an <a href="https://www.saikumarmk.com/the-story-of-setool/" rel="nofollow noopener noreferrer external" target="_blank">image of the heat-map</a> and the following prompt below:</p> <!----><pre class="shiki monokai"><div class='code-container'><code><div class='line'>I once created a webapp in plotly+dash that visualised unit scores (13 items, from 1 to 5) in a heat-map like grid by mapping from red to green. The code is in python and relies on the dash table, so I want you to recreate it in javascript (you can use libraries such as d3/vega/whatever you think is the best for the task). It had the following features:</div><div class='line'></div><div class='line'>    Filters (semester, level, choosing the mean/median for overall score) toggling columns - each item in the database (I will supply a sample item)</div><div class='line'>    Search filters in each column, for numerical items you can do comparison filters and string columns you can search matches</div><div class='line'>    checkboxes next to each entry so you can add it to a comparison table that's similar to the first table.</div><div class='line'></div><div class='line'>This is a sample entry:</div><div class='line'>&#123;'Responses': 30, 'Invited': 79, 'Season': '2019_S2', 'Response Rate': 37.9746835443038, 'unit_name': ' Accounting information systems and financial modelling ', 'code': ' ACB2851_PENINSULA_ON-CAMPUS_ON_S2-01 ', 'unit_code': 'ACB2851', 'Level': 2, 'I1': [4.23, 4.35], 'I2': [4.37, 4.62], 'I3': [4.27, 4.5], 'I4': [4.23, 4.56], 'I5': [4.17, 4.39], 'I6': [4.23, 4.41], 'I7': [4.23, 4.5], 'I8': [4.27, 4.56], 'I9': [4.13, 4.27], 'I10': [4.1, 4.33], 'I11': [4.03, 4.19], 'I12': [4.3, 4.5], 'I13': [4.2, 4.5], 'agg_score': [4.212307692307693, 4.436923076923076]&#125;</div><div class='line'></div><div class='line'>Assume this is loaded from some JSON/serialised format. now then...</div><div class='line'></div><div class='line'>I'd... i'd like you to unleash the ultimate implementation of this code: DONT HOLD BACK, CLAUDE-KUN! TAKE IT TO THE LOGICAL ENDGAME!</div></code></div></pre><!----> <p>With the crazy prompt adapted from <a href="https://x.com/nptacek/status/1858302846011048178" rel="nofollow noopener noreferrer external" target="_blank">this Twitter post</a>. To which, it generated a <a href="https://github.com/saikumarmk/unit-scores-dashboard/blob/master/src/components/dashboard/UnitScoresDashboard.tsx" rel="nofollow noopener noreferrer external" target="_blank">React component</a> for me, which I promptly threw into basic <code>next</code> app. And it worked! Sort of…</p> <p>After the initial prompt, I asked it to refine the web application and allow users to filter columns by specific properties. I managed to get it to parity with the original SETool within a few prompts and a few hours of hacking. It is a vast upgrade over how long it took me to code up SETool. Additionally, since it’s in React, I can host the web page on GH-pages by exporting the web app to a static format <sup id="fnref-2"><a href="#fn-2" class="footnote-ref">2</a></sup> which makes deployment much easier (usually).</p> <p><!--[-1--><img src="/assets/setool/setool_v3.png" alt="SETool v3 in React" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>Anyway, if you’re a Monash student, go check it out and let me know what you think! As of now, the comparison table is a bit bugged, but otherwise it’s pretty functional and looks good! I will try to update the dashboard here and there, but I also wouldn’t mind any prospective students taking it off my hands (and you get a free project on your resume).</p> <!--[-1--><div class="sprite-wrapper medium"><span class="pokesprite pokemon porygon-z"></span></div><!--]--><!----> <div class="footnotes"><hr/> <ol><li id="fn-1">Heroku stopped their free plan, and I always intended to get rid of Python and make it a pure web-app.<a href="#fnref-1" class="footnote-backref">↩</a></li> <li id="fn-2">You can use the <code>npm</code> package <a href="https://www.npmjs.com/package/gh-pages" rel="nofollow noopener noreferrer external" target="_blank">gh-pages</a> with a bit of configuration to export all your styles.<a href="#fnref-2" class="footnote-backref">↩</a></li></ol></div><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="blog-post" scheme="https://https:///?tags=blog-post" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Building a Circles Clone for Monash]]></title>
    <link href="https://https:///circles-clone-requirements" />
    <id>https://https:///circles-clone-requirements</id>
    <published>2024-10-09T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.251Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><p>I’ve previously written on Circles, an amazing, student-built course planner maintained by DevSoc, a society that used to be a branch of CSESoc. Monash has its course planner, named <a href="https://monplan.apps.monash.edu/" rel="nofollow noopener noreferrer external" target="_blank">MonPlan</a> which was formerly student-led by people such as Eric Jiang. Unlike UNSW, however, the project came into the hands of Monash Esolutions, which meant that development would then be relegated to Monash. While MonPlan is a great base for developing a Circles clone, it has not seen any development in a while, primarily due to internal politics.</p> <p>During my time at Monash, I took several swings at looking for a consistent method of retrieving unit requisites, with my most successful attempt with a microservice that MonPlan uses giving rise to the Monash Graph available on my site. I also learned about how Circles was developed from some DevSoc directors who also interned at Canva with me, along with some other online friends. Since I’ve developed a reliable way to scrape and format the requisites for a unit reliably, I believe that the Monash student community has the potential to develop resources that are similar to Circles. This way, the resources are more relevant to students as it’s developed by students, and can be passed down.</p> <p>I also think Monash is in a slightly better position than other universities because we have an exposed microservice that gives (mostly) correct requisites.</p> <h2 id="an-upgraded-handbook"><a href="#an-upgraded-handbook">An Upgraded Handbook</a></h2> <p>I rewrote my handbook scraper in Go, which retrieves the units, courses, and areas of study (aos) from the Monash handbook. I’ve only made use of the units to draw the unit graph on my site, but we can also format the courses and areas of study. The immediate implication is that we can use this for course auto-planning, along with verifying the completion of a course map.</p> <p>An immediate enhancement I can see is a better handbook, baked into the course planner like Circles does <a href="https://circles.csesoc.app/course-selector" rel="nofollow noopener noreferrer external" target="_blank">here</a>. This could factor in your selected course and aos and allow for smart selection. Some easy wins:</p> <ul><li>Developing an enhanced handbook experience</li> <li>Tells you what units you unlock by undertaking a unit (an indirect recommendation system)</li> <li>An explicit recommendation system (using the former, and your other units)</li> <li>The explicit cost of units, pulled from the SCA band and an up-to-date cost calculator</li> <li>Gives you proper, strictly formatted requisites for a unit that are easier to interpret</li> <li>Think, of a DAG representing the units required to unlock a unit</li></ul> <p>These features fall out from the requisite data we already possess.</p> <h2 id="the-monash-unit-graph"><a href="#the-monash-unit-graph">The Monash Unit Graph</a></h2> <p>The Monash Unit Graph on my site is a fun experience but doesn’t provide much use to students who want to interpret the data. I wanted to replicate the <a href="https://circles360.github.io/#/3778/COMPA1/FINSA2" rel="nofollow noopener noreferrer external" target="_blank">original Circles</a> with their click-to-complete graph view, though I ended up adding a build mode that visualises units as a DAG.</p> <p>Some things I think can be done:</p> <ul><li>Using a DAG as a base to create more detailed progression diagrams that can be used in guides</li> <li>A click-to-add view which stores the selection data from the other modes for visualisation purposes</li></ul> <h2 id="other-features"><a href="#other-features">Other features</a></h2> <p>Some more features off the top of my head:</p> <ul><li>Auto-planning with operations research (basically 2SAT the problem) similar to how <a href="https://devsoc.atlassian.net/wiki/spaces/C/pages/754356/Auto-Planning" rel="nofollow noopener noreferrer external" target="_blank">Circles does it</a></li> <li>This requires representing the requisites as an AST, which is how they unlock new units when you add units</li> <li>The semester planner; I don’t think this is a big priority since MonPlan does a good job at this</li> <li>An API for querying; this is just a natural consequence of hosting stuff on a site and having an API from which to request resources.</li></ul> <p>Additionally, incorporating SETU data into the previously mentioned software. The data can be exported and then mined for the user ratings for each unit. Visualising the data gives you a way to compare units with the different learning outcomes.</p><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="university" scheme="https://https:///?tags=university" />
    <category term="graph" scheme="https://https:///?tags=graph" />
  </entry>
  <entry>
    <title type="html"><![CDATA[A Brief, Mathematical Explanation of Big O]]></title>
    <link href="https://https:///note-on-bigo" />
    <id>https://https:///note-on-bigo</id>
    <published>2024-05-31T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><p>Big O is commonly used in the context of computer science, specifically about the time complexity of algorithms. You’ll often hear things such as “Binary search is <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>log</mi><mo>⁡</mo><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(\log(n))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mop">log</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">))</span></span></span></span><!----></span>”, or “O(n) means linear time”, though I often find that students have a poor understanding of what Big O is.</p> <h3 id="what-is-big-o-mathematically"><a href="#what-is-big-o-mathematically">What is Big O, mathematically?</a></h3> <p>Big O is a mathematical notation which describes the behaviour of a function (<span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><mi mathvariant="double-struck">R</mi><mo>→</mo><mi mathvariant="double-struck">R</mi></mrow><annotation encoding="application/x-tex">f:\mathbb{R}\to\mathbb{R}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mspace"></span><span class="mrel">:</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbb">R</span><span class="mspace"></span><span class="mrel">→</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbb">R</span></span></span></span><!----></span>) as the function argument tends towards infinity. You can also look at the behaviour as the argument approaches some value but we’ll ignore that. In particular, it describes the growth of a function as it tends towards <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∞</mi></mrow><annotation encoding="application/x-tex">\infty</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∞</span></span></span></span><!----></span>.</p> <p>For real-valued functions <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi></mrow><annotation encoding="application/x-tex">g</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">g</span></span></span></span><!----></span>, we write <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mi>O</mi><mo stretchy="false">(</mo><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(x) = O(g(x))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord mathnormal">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">))</span></span></span></span><!----></span> or <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>∈</mo><mi>O</mi><mo stretchy="false">(</mo><mi>g</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f \in O(g)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord mathnormal">g</span><span class="mclose">)</span></span></span></span><!----></span> (which is more correct, but CS students are more used to the former), that is, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span></span></span></span><!----></span> is big O of <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi></mrow><annotation encoding="application/x-tex">g</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">g</span></span></span></span><!----></span>. For <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>∈</mo><mi>O</mi><mo stretchy="false">(</mo><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(x)\in O(g(x))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord mathnormal">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">))</span></span></span></span><!----></span>, that means there exists <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi><mo>&gt;</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">M &gt; 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">M</span><span class="mspace"></span><span class="mrel">&gt;</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mn>0</mn></msub><mo>∈</mo><mi mathvariant="double-struck">R</mi></mrow><annotation encoding="application/x-tex">x_0 \in \mathbb{R}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbb">R</span></span></span></span><!----></span> such that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∣</mi><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mi mathvariant="normal">∣</mi><mo>≤</mo><mi>M</mi><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">|f(x)| \leq M g(x)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∣</span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mord">∣</span><span class="mspace"></span><span class="mrel">≤</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">M</span><span class="mord mathnormal">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span><!----></span>, for all <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≥</mo><msub><mi>x</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">x \geq x_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">x</span><span class="mspace"></span><span class="mrel">≥</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>. Intuitively, it means <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi></mrow><annotation encoding="application/x-tex">g</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">g</span></span></span></span><!----></span> eventually bounds <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span></span></span></span><!----></span>, ignoring constant multiples, or smaller terms that get dominated.</p> <p>As an example, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><msup><mi>n</mi><mn>2</mn></msup><mo>+</mo><mi>n</mi><mo>∈</mo><mi>O</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">2n^2+n \in O(n^2)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">2</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span> because <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>&lt;</mo><msup><mi>n</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">n &lt; n^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">&lt;</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><!----></span> for <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>&gt;</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n&gt;1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">&gt;</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span>, so <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><msup><mi>n</mi><mn>2</mn></msup><mo>+</mo><mi>n</mi><mo>&lt;</mo><mn>2</mn><msup><mi>n</mi><mn>2</mn></msup><mo>+</mo><msup><mi>n</mi><mn>2</mn></msup><mo>=</mo><mn>3</mn><msup><mi>n</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">2n^2+n&lt; 2n^2+n^2 = 3n^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">2</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">&lt;</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">2</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">3</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><!----></span>, and thus for all <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>≥</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n \geq 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">≥</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span>, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><msup><mi>n</mi><mn>2</mn></msup><mo>+</mo><mi>n</mi><mo>≤</mo><mn>3</mn><msup><mi>n</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">2n^2+n \leq 3n^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">2</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">≤</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">3</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><!----></span>. In the field of mathematics, Big O notation is used in Taylor series, to describe terms that grow at a certain rate but are mostly irrelevant, or encode an “error” term. However, if we go off the definition from prior, we also find that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>log</mi><mo>⁡</mo><mi>n</mi><mo>∈</mo><mi>O</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\log n \in O(n^2)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span>, despite logarithms not looking very quadratic. A better way to informally think about big O in particular is if <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>∈</mo><mi>O</mi><mo stretchy="false">(</mo><mi>g</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f\in O(g)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord mathnormal">g</span><span class="mclose">)</span></span></span></span><!----></span>, that means the growth rate of <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span></span></span></span><!----></span> is bounded above by <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi></mrow><annotation encoding="application/x-tex">g</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">g</span></span></span></span><!----></span>.</p> <h3 id="the-ram-model-of-computation"><a href="#the-ram-model-of-computation">The RAM model of Computation</a></h3> <p>Now we build up to Big O in computer science. For a given algorithm, we want a way to measure the number of steps taken to execute the algorithm, with respect to some input size. We’re not interested in language-specific features, so we look to the Random Access Machine (RAM), an abstract model that we use to count the number of steps executed in an algorithm. We assume the following:</p> <ul><li>Operations such as arithmetic and comparison on integers, assignment, memory access, and function calling takes up one step</li> <li>A loop is built off a variable number of simple operations. So iterating over <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>10</mn></mrow><annotation encoding="application/x-tex">10</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">10</span></span></span></span><!----></span> objects would consist of <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>10</mn></mrow><annotation encoding="application/x-tex">10</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">10</span></span></span></span><!----></span> simple operations.</li></ul> <p>With the RAM model, we can now perform time complexity analysis. That is, we look at the inputs to a function that could cause the number of execution steps to increase. Consider the function below with integer input <code>n</code>:</p> <!----><pre class="shiki monokai"><div class='code-container'><code><div class='line'>function f(n):</div><div class='line'> sum = 0  # 1 operation</div><div class='line'> for i=1 to i=n do:</div><div class='line'>    for j=1 to j=n do:</div><div class='line'>        for k=1 to k=n do:</div><div class='line'>            sum = sum+i+j+k # This is 5 operations </div><div class='line'> return sum</div></code></div></pre><!----> <p>Let <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span> be the number of steps it takes for <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span></span></span></span><!----></span> to run on an input <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span></span></span></span><!----></span>. The innermost operation is nested, so we use summations to tabulate the number of steps it takes. Then:</p> <p><span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mn>1</mn><mo>+</mo><msubsup><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><msubsup><mo>∑</mo><mrow><mi>k</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mn>3</mn><mo>=</mo><mn>1</mn><mo>+</mo><mn>5</mn><msup><mi>n</mi><mn>3</mn></msup><mo>∈</mo><mi>O</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>3</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n) = 1+ \sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n 3= 1+5 n^3 \in O(n^3)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop"><span class="mop op-symbol small-op">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mop"><span class="mop op-symbol small-op">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mop"><span class="mop op-symbol small-op">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">k</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mord">3</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">5</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span></p> <p>We say that the time complexity of the algorithm <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span></span></span></span><!----></span> is <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>3</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n^3)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span>. We use Big O because we’re not currently concerned with the constants, or smaller terms (though you shouldn’t just disregard them). If you wanted to examine the space complexity of an algorithm, you would carry out a similar process, except you would count points where new memory is allocated. As an immediate result, you shouldn’t be able to have a space complexity that’s larger than your time complexity.</p> <h3 id="recursive-functions"><a href="#recursive-functions">Recursive Functions</a></h3> <p>In the case that your function is recursive, it becomes a bit more intuitive to reason about the time complexity of your function. Consider the famous factorial function, defined as:</p> <!----><pre class="shiki monokai"><div class='code-container'><code><div class='line'>function factorial(n):</div><div class='line'> if n &gt; 0:</div><div class='line'>    return n*factorial(n-1)</div><div class='line'> else:</div><div class='line'>    return 1</div></code></div></pre><!----> <p>Suppose <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span> is our time complexity function for <code>factorial</code>, where <code>n</code> is the input. If we’re counting the number of steps it takes for <code>factorial(n)</code>, we’d need to know how many steps it takes <code>factorial(n-1)</code> to execute. We do one comparison operation, so we can say that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">T(n) = T(n-1)+1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span>. Remember that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n-1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><!----></span> is the time complexity function for <code>factorial(n-1)</code>. We could keep doing this until we hit the base case, corresponding to <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mn>0</mn><mo stretchy="false">)</mo><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">T(0)=1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord">0</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> since we’re doing one operation (returning an integer). Now, all we need is a way to solve this relation.</p> <h3 id="solving-recurrence-relations-via-telescoping"><a href="#solving-recurrence-relations-via-telescoping">Solving recurrence relations via Telescoping</a></h3> <p>From what I’ve seen, telescoping is a skill that seems seldom taught. If you want to figure out what a closed-form solution to the recurrence relation underpins the time complexity of your function, you could always throw it into a CAS such as Wolfram Alpha, or you could telescope the relation. The idea behind telescoping is to progressively write out the nth term of a relation in terms of more and more terms till you can discern a pattern.</p> <p>Let’s revisit our factorial example. We had the information <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">T(n)=T(n-1)+1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">T(1)=1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> which we use to construct the relation:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">{</mo><mtable rowspacing="0.36em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>+</mo><mn>1</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mtext>if </mtext><mi>n</mi><mo>&gt;</mo><mn>0</mn></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mtext>if </mtext><mi>n</mi><mo>=</mo><mn>0</mn></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">T(n) =\begin{cases} T(n-1) + 1 &amp; \text{if } n &gt; 0 \\1 &amp; \text{if } n = 0\end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span><span class="mord">1</span></span></span><span class="pstrut"><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="arraycolsep"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">&gt;</span><span class="mspace"></span><span class="mord">0</span></span></span><span class="pstrut"><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span><!----></div> <p>So, we know that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">T(n)=T(n-1)+1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span>, but we also know that T<span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>=</mo><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>2</mn><mo stretchy="false">)</mo><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">(n-1)=T(n-2)+1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">2</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span>. Substituting for <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n-1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><!----></span> gives us:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>2</mn><mo stretchy="false">)</mo><mo>+</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">T(n) =T(n-2)+2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">2</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">2</span></span></span></span></span><!----></div> <p>We can keep going back, but it becomes clear that we can write <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mi>k</mi><mo stretchy="false">)</mo><mo>+</mo><mi>k</mi></mrow><annotation encoding="application/x-tex">T(n)=T(n-k)+k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">−</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span></span></span></span><!----></span>. We want to go all the way backwards till we hit the base case, where <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><mi>k</mi></mrow><annotation encoding="application/x-tex">n=k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span></span></span></span><!----></span>. Putting this into our relation gives <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>T</mi><mo stretchy="false">(</mo><mn>0</mn><mo stretchy="false">)</mo><mo>+</mo><mi>n</mi><mo>=</mo><mi>n</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">T(n)=T(0)+n = n+1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord">0</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span>. This makes sense to us since it takes <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n+1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span></span></span></span><!----></span> multiplications to get to <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo stretchy="false">!</mo></mrow><annotation encoding="application/x-tex">n!</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mclose">!</span></span></span></span><!----></span>.</p> <p>Telescoping won’t solve every recurrence you have. As an exercise, try to find the complexity of the recursive Fibonacci function. Sketch a diagram of the call-tree, and reason about how many operations you may end up with.</p> <h3 id="examples"><a href="#examples">Examples</a></h3> <p>Let’s attempt to determine the time complexity of some functions.</p> <!----><pre class="shiki monokai"><div class='code-container'><code><div class='line'>function binary_search(container, start, end, target):</div><div class='line'> if start &lt;= end:</div><div class='line'>    middle = floor((start+end)/2)</div><div class='line'>    if container[middle] == target:</div><div class='line'>        return middle</div><div class='line'>    if container[middle] &gt; target:</div><div class='line'>        return binary_search(container, start, middle)</div><div class='line'>    if container[middle] &lt; target:</div><div class='line'>        return binary_search(container, middle,end)</div><div class='line'> else:</div><div class='line'>    return -1         </div></code></div></pre><!----> <p>Let <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span> be the number of steps it takes for <code>binary_search</code> to execute where <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span></span></span></span><!----></span> is the length of the container (assume it’s an array). For a list of size <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span></span></span></span><!----></span>, binary search reduces the problem to binary searching a list of size <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mi mathvariant="normal">/</mi><mn>2</mn></mrow><annotation encoding="application/x-tex">n/2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mord">/2</span></span></span></span><!----></span>, with a few operations for comparison. That means we can write <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span> as a recurrence relation:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">{</mo><mtable rowspacing="0.36em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>T</mi><mrow><mo fence="true">(</mo><mfrac><mi>n</mi><mn>2</mn></mfrac><mo fence="true">)</mo></mrow><mo>+</mo><mi>a</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mtext>if </mtext><mi>n</mi><mo>&gt;</mo><mn>1</mn></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>c</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mtext>if </mtext><mi>n</mi><mo>=</mo><mn>1</mn></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">T(n) =\begin{cases} T\left(\frac{n}{2}\right) + a &amp; \text{if } n &gt; 1 \\c &amp; \text{if } n = 1\end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">T</span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size1">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter"><span class="delimsizing size1">)</span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span><span class="mord mathnormal">a</span></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">c</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="arraycolsep"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">&gt;</span><span class="mspace"></span><span class="mord">1</span></span></span><span class="pstrut"><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span><!----></div> <p>From here, you may use the Master theorem (if you remember it), or telescope the recurrence relation to solve it:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mi mathvariant="normal">/</mi><mn>2</mn><mo stretchy="false">)</mo><mo>+</mo><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mi mathvariant="normal">/</mi><mn>4</mn><mo stretchy="false">)</mo><mo>+</mo><mi>a</mi><mo stretchy="false">)</mo><mo>+</mo><mi>a</mi><mo>=</mo><mo stretchy="false">(</mo><mo stretchy="false">(</mo><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mi mathvariant="normal">/</mi><mn>8</mn><mo stretchy="false">)</mo><mo>+</mo><mi>a</mi><mo stretchy="false">)</mo><mo>+</mo><mi>a</mi><mo stretchy="false">)</mo><mo>+</mo><mi>a</mi><mo>=</mo><mo>⋯</mo><mspace linebreak="newline"></mspace><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mi mathvariant="normal">/</mi><msup><mn>2</mn><mi>k</mi></msup><mo stretchy="false">)</mo><mo>+</mo><mi>a</mi><mi>k</mi></mrow><annotation encoding="application/x-tex">T(n)=T(n/2)+O(1) =(T(n/4)+a)+a = ((T(n/8)+a)+a)+a = \cdots \\T(n) = T(n/2^k)+ak</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mord">/2</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">(</span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mord">/4</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">a</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mopen">((</span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mord">/8</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">a</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="minner">⋯</span></span><span class="mspace newline"></span><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mord">/</span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">k</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">ak</span></span></span></span></span><!----></div> <p>We hit the base case when <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mi mathvariant="normal">/</mi><msup><mn>2</mn><mi>k</mi></msup><mo>=</mo><mn>1</mn><mtext>  </mtext><mo>⟺</mo><mtext>  </mtext><mi>n</mi><mo>=</mo><msup><mn>2</mn><mi>k</mi></msup></mrow><annotation encoding="application/x-tex">n/2^k =1 \iff n=2^k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mord">/</span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">k</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">1</span><span class="mspace"></span><span class="mspace"></span><span class="mrel">⟺</span><span class="mspace"></span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">k</span></span></span></span></span></span></span></span></span></span></span><!----></span> which yields <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mo>=</mo><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>n</mi></mrow><annotation encoding="application/x-tex">k = \log_2 n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">k</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop"><span class="mop">log</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mord mathnormal">n</span></span></span></span><!----></span>. Substituting this back in gives us <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>T</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo><mo>+</mo><mi>a</mi><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>n</mi><mtext> </mtext><mo>=</mo><mi>c</mi><mo>+</mo><mi>a</mi><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>n</mi></mrow><annotation encoding="application/x-tex">T(n) = T(1) + a \log_2 n  = c + a\log_2 n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">a</span><span class="mspace"></span><span class="mop"><span class="mop">log</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mord mathnormal">n</span><span class="mord"> </span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">c</span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">a</span><span class="mspace"></span><span class="mop"><span class="mop">log</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mord mathnormal">n</span></span></span></span><!----></span>. That is, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>∈</mo><mi>O</mi><mo stretchy="false">(</mo><mi>log</mi><mo>⁡</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n) \in O(\log n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span>. Note that the base is irrelevant here due to the change in the base formula. You can also see that it would be very easy to convert the iterative binary search into a recursive binary search because the problem reduces to binary searching on a list half the size of the original list repeatedly till you hit a base case.</p> <!----><pre class="shiki monokai"><div class='code-container'><code><div class='line'>function g(n):</div><div class='line'> for i=1 to i=n do:</div><div class='line'>    for j=1 to j=n/i do:</div><div class='line'>        mystery(n) # Assume this function takes n steps to execute</div><div class='line'></div></code></div></pre><!----> <p>We now have an algorithm <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi></mrow><annotation encoding="application/x-tex">g</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">g</span></span></span></span><!----></span> which calls a mystery function <code>mystery</code>. You’re told that it takes <code>n</code> steps to execute <code>mystery(n)</code>. So it’s time to figure out the time complexity <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span> for <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi></mrow><annotation encoding="application/x-tex">g</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">g</span></span></span></span><!----></span>. We write out the following summation:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></munderover><munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mrow><mi>n</mi><mi mathvariant="normal">/</mi><mi>i</mi></mrow></munderover><mi>n</mi></mrow><annotation encoding="application/x-tex">T(n)=\sum_{i=1}^n \sum_{j=1}^{n/i} n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mtight">/</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="mord mathnormal">n</span></span></span></span></span><!----></div> <p>You can pull out the <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span></span></span></span><!----></span>, since it’s not a summation variable, leaving us with:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>n</mi><mo>⋅</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></munderover><munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mrow><mi>n</mi><mi mathvariant="normal">/</mi><mi>i</mi></mrow></munderover><mn>1</mn><mo>=</mo><mi>n</mi><mo>⋅</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></munderover><mi>n</mi><mi mathvariant="normal">/</mi><mi>i</mi><mo>=</mo><msup><mi>n</mi><mn>2</mn></msup><mo>⋅</mo><munder><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow></munder><mn>1</mn><mi mathvariant="normal">/</mi><mi>i</mi></mrow><annotation encoding="application/x-tex">T(n) =n \cdot \sum_{i=1}^n \sum_{j=1}^{n/i} 1 = n \cdot \sum_{i=1}^n n/i = n^2 \cdot \sum_{i=1} 1/i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mtight">/</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="mord">1</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="mord mathnormal">n</span><span class="mord">/</span><span class="mord mathnormal">i</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mbin">⋅</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="mop op-symbol large-op">∑</span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="mord">1/</span><span class="mord mathnormal">i</span></span></span></span></span><!----></div> <p>The summation on the right is the sum of the first <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span></span></span></span><!----></span> terms of the Harmonic series. A pretty niche approximation is <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mn>1</mn><mi mathvariant="normal">/</mi><mi>i</mi><mo>≈</mo><mi>ln</mi><mo>⁡</mo><mi>n</mi></mrow><annotation encoding="application/x-tex">\sum_{i=1}^n 1/i \approx \ln n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mop"><span class="mop op-symbol small-op">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mord">1/</span><span class="mord mathnormal">i</span><span class="mspace"></span><span class="mrel">≈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mop">ln</span><span class="mspace"></span><span class="mord mathnormal">n</span></span></span></span><!----></span>. We may substitute this <em>approximation</em> to get <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>≈</mo><msup><mi>n</mi><mn>2</mn></msup><mi>ln</mi><mo>⁡</mo><mi>n</mi><mo>∈</mo><mi>O</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>2</mn></msup><mi>ln</mi><mo>⁡</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n)\approx n^2 \ln n \in O(n^2 \ln n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">≈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mop">ln</span><span class="mspace"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mop">ln</span><span class="mspace"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span>.</p> <h2 id="other-asymptotics"><a href="#other-asymptotics">Other Asymptotics</a></h2> <p>There are other asymptotic terms for describing the limiting behaviour of a function. These terms appear in computer science in a range of forms, though they’ll more commonly appear in mathematics. I add this section because VCE Algorithmics does a horrifying job of relating the various notations to the concepts of ‘best-case’, ‘average-case’, or ‘worst-case’ time complexity. They are completely separate concepts, but we can use <em>any</em> of the notations mentioned here to describe what the time complexity is like.</p> <h3 id="theta"><a href="#theta">Theta</a></h3> <p>We may tighten the idea of big Oh by also bounding it from below. We introduce <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Θ</mi></mrow><annotation encoding="application/x-tex">\Theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">Θ</span></span></span></span><!----></span>. For <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>∈</mo><mi mathvariant="normal">Θ</mi><mo stretchy="false">(</mo><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(x)\in\Theta(g(x))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">Θ</span><span class="mopen">(</span><span class="mord mathnormal">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">))</span></span></span></span><!----></span>, that means there exists <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>M</mi><mn>1</mn></msub><mo>&gt;</mo><msub><mi>M</mi><mn>2</mn></msub><mo>&gt;</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">M_1 &gt; M_2 &gt; 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">&gt;</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">&gt;</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mn>0</mn></msub><mo>∈</mo><mi mathvariant="double-struck">R</mi></mrow><annotation encoding="application/x-tex">x_0 \in \mathbb{R}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbb">R</span></span></span></span><!----></span> such that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>M</mi><mn>1</mn></msub><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>≤</mo><mi mathvariant="normal">∣</mi><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mi mathvariant="normal">∣</mi><mo>≤</mo><msub><mi>M</mi><mn>2</mn></msub><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">M_1 g(x) \leq |f(x)| \leq M_2 g(x)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord mathnormal">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">≤</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">∣</span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mord">∣</span><span class="mspace"></span><span class="mrel">≤</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord mathnormal">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span><!----></span>, for all <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≥</mo><msub><mi>x</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">x \geq x_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">x</span><span class="mspace"></span><span class="mrel">≥</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>. So, while <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>n</mi><mn>2</mn></msup><mo>=</mo><mi>O</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>3</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">n^2 = O(n^3)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span>, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>n</mi><mn>2</mn></msup><mo mathvariant="normal">≠</mo><mi mathvariant="normal">Θ</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>3</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">n^2 \neq \Theta(n^3)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">Θ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span>. You may commonly see this used as a more precise descriptor for the time complexity of an algorithm, since it pins down the lower bound as well, preventing people from asking whether <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>log</mi><mo>⁡</mo><mi>n</mi><mo>∈</mo><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\log n \in O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span>, because while the intent may have been to say that the function is roughly linear, you could also say that the function could be sub-linear.</p> <h3 id="omega"><a href="#omega">Omega</a></h3> <p>Big Omega has two definitions that vary slightly, but we’ll be using the definition that indicates an asymptotic lower bound.  For <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>∈</mo><mi mathvariant="normal">Ω</mi><mo stretchy="false">(</mo><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(x)\in\Omega(g(x))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">Ω</span><span class="mopen">(</span><span class="mord mathnormal">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">))</span></span></span></span><!----></span>, that means there exists <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi><mo>&gt;</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">M &gt; 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">M</span><span class="mspace"></span><span class="mrel">&gt;</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mn>0</mn></msub><mo>∈</mo><mi mathvariant="double-struck">R</mi></mrow><annotation encoding="application/x-tex">x_0 \in \mathbb{R}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbb">R</span></span></span></span><!----></span> such that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∣</mi><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mi mathvariant="normal">∣</mi><mo>&gt;</mo><mi>M</mi><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">|f(x)| &gt; M g(x)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∣</span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mord">∣</span><span class="mspace"></span><span class="mrel">&gt;</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">M</span><span class="mord mathnormal">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span><!----></span>, for all <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≥</mo><msub><mi>x</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">x \geq x_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">x</span><span class="mspace"></span><span class="mrel">≥</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>. For example, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msqrt><mi>n</mi></msqrt><mo>∈</mo><mi mathvariant="normal">Ω</mi><mo stretchy="false">(</mo><mi>log</mi><mo>⁡</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\sqrt{n} \in \Omega(\log n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="svg-align"><span class="pstrut"></span><span class="mord"><span class="mord mathnormal">n</span></span></span><span class="pstrut"><span class="hide-tail"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewBox="0 0 400000 1080" preserveAspectRatio="xMinYMin slice"><path d="M95,702c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,-221l0 -0c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47zM834 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">Ω</span><span class="mopen">(</span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span>, because the square root function asymptotically grows faster than <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>log</mi><mo>⁡</mo><mi>n</mi></mrow><annotation encoding="application/x-tex">\log n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">n</span></span></span></span><!----></span>. Additionally, comparison-based sorting algorithms take <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Ω</mi><mo stretchy="false">(</mo><mi>n</mi><mi>log</mi><mo>⁡</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\Omega(n \log n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">Ω</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span> steps to execute (no optimisations) due to how many comparisons you need to compare a whole list. A sketch of the proof would involve drawing out the tree of comparisons and reasoning about what a lower-bound on the number of comparisons would be.</p> <h3 id="little-oh"><a href="#little-oh">Little Oh</a></h3> <p>Little Oh is a stronger variant of Big Oh. For <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>∈</mo><mi>o</mi><mo stretchy="false">(</mo><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(x)\in o(g(x))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">o</span><span class="mopen">(</span><span class="mord mathnormal">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">))</span></span></span></span><!----></span>, that means there exists <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi><mo>&gt;</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">M &gt; 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">M</span><span class="mspace"></span><span class="mrel">&gt;</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">0</span></span></span></span><!----></span> and <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mn>0</mn></msub><mo>∈</mo><mi mathvariant="double-struck">R</mi></mrow><annotation encoding="application/x-tex">x_0 \in \mathbb{R}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathbb">R</span></span></span></span><!----></span> such that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∣</mi><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mi mathvariant="normal">∣</mi><mo>&lt;</mo><mi>M</mi><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">|f(x)| &lt; M g(x)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">∣</span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mord">∣</span><span class="mspace"></span><span class="mrel">&lt;</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">M</span><span class="mord mathnormal">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span><!----></span>, for all <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≥</mo><msub><mi>x</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">x \geq x_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">x</span><span class="mspace"></span><span class="mrel">≥</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span></span></span><!----></span>. This means that while <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>n</mi><mn>2</mn></msup><mo>=</mo><mi>O</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">n^2 = O(n^2)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">O</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span>, <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>n</mi><mn>2</mn></msup><mo>∉</mo><mi>o</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">n^2 \not\in o(n^2)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span></span><span class="base"><span class="strut"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">o</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span>, though <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mi>log</mi><mo>⁡</mo><mi>n</mi><mo>=</mo><mi>o</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">n \log n = o(n^2)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">n</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">o</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span>. If <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>∈</mo><mi>o</mi><mo stretchy="false">(</mo><mi>g</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f \in o(g)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">o</span><span class="mopen">(</span><span class="mord mathnormal">g</span><span class="mclose">)</span></span></span></span><!----></span>, we say that <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span></span></span></span><!----></span> is dominated by <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi></mrow><annotation encoding="application/x-tex">g</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">g</span></span></span></span><!----></span> asymptotically. You may find this symbol in number theory, or other areas of maths.</p> <h3 id="the-master-theorem"><a href="#the-master-theorem">The Master Theorem</a></h3> <p>For an algorithm whose time complexity <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span> can be expressed in the form <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>a</mi><mi>T</mi><mrow><mo fence="true">(</mo><mfrac><mi>n</mi><mi>b</mi></mfrac><mo fence="true">)</mo></mrow><mo>+</mo><mi>f</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n) = a T\left(\frac{n}{b}\right) + f(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">a</span><span class="mord mathnormal">T</span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size1">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="pstrut"><span class="frac-line"></span></span><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter"><span class="delimsizing size1">)</span></span></span><span class="mspace"></span><span class="mbin">+</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span> (constants <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo separator="true">,</mo><mi>b</mi></mrow><annotation encoding="application/x-tex">a,b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord mathnormal">b</span></span></span></span><!----></span>, function <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span></span></span></span><!----></span>), we can use the Master theorem to determine an asymptotically tight (<span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Θ</mi></mrow><annotation encoding="application/x-tex">\Theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord">Θ</span></span></span></span><!----></span> notation) bound for <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><!----></span>. Suppose <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>∈</mo><mi mathvariant="normal">Θ</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mi>d</mi></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f \in \Theta(n^d)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">f</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="mord">Θ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><!----></span> where <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi></mrow><annotation encoding="application/x-tex">d</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">d</span></span></span></span><!----></span> is a constant, then:</p> <div class="math math-display"><!----><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>∈</mo><mrow><mo fence="true">{</mo><mtable rowspacing="0.36em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi mathvariant="normal">Θ</mi><mrow><mo fence="true">(</mo><msup><mi>n</mi><mi>d</mi></msup><mo fence="true">)</mo></mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>a</mi><mo>&lt;</mo><msup><mi>b</mi><mi>d</mi></msup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi mathvariant="normal">Θ</mi><mrow><mo fence="true">(</mo><msup><mi>n</mi><mi>d</mi></msup><mi>log</mi><mo>⁡</mo><mi>n</mi><mo fence="true">)</mo></mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>a</mi><mo>=</mo><msup><mi>b</mi><mi>d</mi></msup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi mathvariant="normal">Θ</mi><mrow><mo fence="true">(</mo><msup><mi>n</mi><mrow><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mi>b</mi></msub><mi>a</mi></mrow></msup><mo fence="true">)</mo></mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>a</mi><mo>&gt;</mo><msup><mi>b</mi><mi>d</mi></msup></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">T(n) \in \begin{cases} \Theta \left( n^d \right) &amp; a &lt; b^d \\\Theta \left( n^d \log n \right) &amp; a = b^d \\\Theta \left( n^{\log_b a} \right) &amp; a &gt; b^d\end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">T</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace"></span><span class="mrel">∈</span><span class="mspace"></span></span><span class="base"><span class="strut"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="delimsizinginner delim-size4">⎩</span></span><span class="pstrut"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span><span class="pstrut"><span class="delimsizinginner delim-size4">⎨</span></span><span class="pstrut"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span><span class="pstrut"><span class="delimsizinginner delim-size4">⎧</span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord">Θ</span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size1">(</span></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span></span></span></span></span><span class="mclose delimcenter"><span class="delimsizing size1">)</span></span></span></span></span><span class="pstrut"><span class="mord"><span class="mord">Θ</span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size1">(</span></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span></span></span></span></span><span class="mspace"></span><span class="mop">log</span><span class="mspace"></span><span class="mord mathnormal">n</span><span class="mclose delimcenter"><span class="delimsizing size1">)</span></span></span></span></span><span class="pstrut"><span class="mord"><span class="mord">Θ</span><span class="mspace"></span><span class="minner"><span class="mopen delimcenter"><span class="delimsizing size1">(</span></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mop mtight"><span class="mop mtight"><span class="mtight">l</span><span class="mtight">o</span><span class="mtight">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span><span class="mspace mtight"></span><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span></span><span class="mclose delimcenter"><span class="delimsizing size1">)</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span><span class="arraycolsep"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="mord"><span class="mord mathnormal">a</span><span class="mspace"></span><span class="mrel">&lt;</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span></span></span></span></span></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">a</span><span class="mspace"></span><span class="mrel">=</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span></span></span></span></span></span></span><span class="pstrut"><span class="mord"><span class="mord mathnormal">a</span><span class="mspace"></span><span class="mrel">&gt;</span><span class="mspace"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist"><span class="pstrut"><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist"></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span><!----></div> <p>As an exercise, prove the Master Theorem using the telescoping method shown earlier.</p> <h2 id="conclusion"><a href="#conclusion">Conclusion</a></h2> <p>This was primarily written to test the MathJax on my site since it was annoying to set up. However, I wanted to write up a brief explanation as a reference article since I’m lazy and prefer to point to things rather than repeat myself. It is important to have a strong understanding of complexity analysis, to the point where it becomes subconscious when you write code. As usual, resources are below:</p> <ul><li><a href="https://www.bigocheatsheet.com/" rel="nofollow noopener noreferrer external" target="_blank">Big O Cheatsheet</a></li> <li><a href="https://www.cs.auckland.ac.nz/courses/compsci220s1t/lectures/lecturenotes/GG-lectures/220exercises1.pdf" rel="nofollow noopener noreferrer external" target="_blank">Exercises on Big O</a></li></ul><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="technical" scheme="https://https:///?tags=technical" />
  </entry>
  <entry>
    <title type="html"><![CDATA[The Grad/Intern Playbook: Part 3 - Acing the Interviews]]></title>
    <link href="https://https:///guide-to-tech-3" />
    <id>https://https:///guide-to-tech-3</id>
    <published>2024-03-18T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="introduction"><a href="#introduction">Introduction</a></h2> <p>This is the fourth article in my series. So, you’ve got through the resume screen, and now are facing a barrage of interviews and assessments. How do you best prepare for these interviews? How many interviews are there? What sort of interviews are there? I’ll go over each of the interview formats that I’ve seen in technical roles. While the term assessment can refer to a task that you need to complete to assess your candidacy, it also refers to interview items. I use the term assessment to refer to non-interview assessments and will split this article into assessments/interviews.</p> <h3 id="the-objective-of-interviews"><a href="#the-objective-of-interviews">The Objective of Interviews</a></h3> <p>When it comes to recruitment, the goal is largely based on avoiding a bad hire, whether due to a lack of skills, culture fit, or any other reason. As a university student, you have little to show for yourself in terms of professional experience, which usually raises the bar for the types of assessments you’ll face, in an attempt to differentiate you. Whether this is fair or not is a separate debate that isn’t usually worth having, since countless other people are willing to go through the process that you may think is unfair, or not representative.</p> <p>Not all companies recruit with the same objectives either, some companies look for talent, or people who understand the business in hopes of training them, whereas other companies look for technical talent that they can further train. In short, a company often looks to cull the worst <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>N</mi></mrow><annotation encoding="application/x-tex">N</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mord mathnormal">N</span></span></span></span><!----></span> applicants, rather than hire the best applicants, as evidenced by the numerous interviews.</p> <h3 id="what-sort-of-rounds-are-there"><a href="#what-sort-of-rounds-are-there">What sort of rounds are there?</a></h3> <p>While I called this article “Acing the Interviews”, I’m also talking about pre-screen assessments, such as coding tests, psychometric testing, and other weird assessments. Companies may clump rounds together; they are sometimes called “super-days”, which can be described as a wave of different interviews. All in all, you may expect an onslaught for a given intern application.</p> <p>When it comes to the number of rounds a company has for a role, graduate roles usually have an extra round; what this round could be can vary from another behavioural interview to another set of technical interviews. The general rule of thumb is that quantitative trading firms have the most rounds, followed closely by big tech companies, then most other companies. Smaller companies or startups have the added benefit of usually not needing to filter for as many people, and recruitment could be as simple as a discussion for an hour.</p> <h1 id="pre-interview-assessments"><a href="#pre-interview-assessments">Pre-Interview Assessments</a></h1> <p>Before you’re able to prove yourself in an interview, companies will subject you to a variety of silly assessments, including Overcooked, random pattern matching tests, or an MBTI test. Yes, I think they’re full of shit as well, but you’re probably not in a position to be above them at this point. Such is the life of a student. The extent to which you can prepare for this can range from extensive practice to just biting the bullet, some tests are just stupid.</p> <h2 id="hackerrank--coding-tests"><a href="#hackerrank--coding-tests">HackerRank / Coding Tests</a></h2> <p>The HackerRank. What else can be said about it? A company wants to filter out people who can’t write a line of code to save their lives, so they ask you to complete a coding assessment. The coding test typically consists of a set of Leetcode/HackerRank style questions, with a set of visible test cases, that and not visible to you. Your goal is to pass enough test cases to make it to the next round. The threshold for passing depends on the company, sometimes they just want to see a response, even if it’s not correct, while other companies may look at people who completed the test quickly.</p> <p>It’s worth noting that these assessment sites can pick up on cheating attempts, such as changing tabs, though not all companies care if you open another tab. I don’t condone cheating, but you should be smart in what you do. So, how do you prepare for one of these assessments?</p> <h3 id="preparation-strategies"><a href="#preparation-strategies">Preparation Strategies</a></h3> <p>The answer is Leetcode. There are two rounds where Leetcode comes in handy; the coding assessment, and the technical interview. When it comes to what problems you should solve, there are curated lists of 75 to 150 problems that cover topics that are most likely to appear on a technical assessment.</p> <ul><li><a href="https://www.techinterviewhandbook.org/grind75" rel="nofollow noopener noreferrer external" target="_blank">Grind75, a customisable study plan based on how much time you have</a></li> <li><a href="https://neetcode.io/roadmap" rel="nofollow noopener noreferrer external" target="_blank">Neetcode 150, a similar study plan</a></li> <li><a href="https://leetcode.com/studyplan/top-interview-150/" rel="nofollow noopener noreferrer external" target="_blank">Leetcode’s top interview 150</a></li></ul> <p>The content in these study plans follows a standard data structures and algorithms course at your university, and you may have an easier time approaching questions from certain topics after seeing them in class. Assuming you’re familiar with a DSA class, the below resources build on the topics you would have seen in class. Some students also elect to use competitive programming sites, such as Codeforces, Codechef, AtCoder, etc, and participate in competitions which can supplement your practice but are often overkill for most places that may not even ask for technical problems.</p> <ul><li><a href="https://www.amazon.com.au/Cracking-Coding-Interview-Programming-Questions/dp/0984782850" rel="nofollow noopener noreferrer external" target="_blank">Cracking the Coding Interview (available on Libgen)</a></li> <li><a href="https://hackernoon.com/14-patterns-to-ace-any-coding-interview-question-c5bb3357f6ed" rel="nofollow noopener noreferrer external" target="_blank">14 patterns to ace any coding interview (available on Libgen as Grokking the Coding Interview)</a></li> <li><a href="https://www.algorist.com/" rel="nofollow noopener noreferrer external" target="_blank">The Algorithm Design Manual</a></li> <li><a href="https://www.amazon.com.au/Introduction-Algorithms-Thomas-Dartmouth-College/dp/0262033844" rel="nofollow noopener noreferrer external" target="_blank">Introduction to Algorithms (CLRS)</a>, though this is more dense and designed for a course in algorithms and data structures</li></ul> <p>Beyond general problem-solving preparation, you should also be able to code in one of the languages that HackerRank lets you pick from. Some companies don’t limit the languages you can choose from; Atlassian lets you choose any commonly used language. Optiver and IMC limit you to C, C++, and Java, which means you should be able to use the respective standard libraries in addition to the basics of programming. My advice is to warm up before you attempt an OA, as you may be rusty on specific data structures, or language-specific context. A list of common data structures you should know to use/implement include:</p> <ul><li><strong>Arrays</strong>: <ul><li>Python: <code>list</code></li> <li>Java: <code>Array</code>, <code>ArrayList</code></li> <li>C++: <code>std::vector</code></li></ul></li> <li><strong>Stack</strong>: <ul><li>Python: <code>list</code> with <code>pop()</code></li> <li>Java: <code>java.util.Stack</code></li> <li>C++: <code>std::deque</code></li></ul></li> <li><strong>Queue</strong>: <ul><li>Python: <code>collections.deque</code></li> <li>Java: <code>java.util.Queue</code></li> <li>C++: <code>std::deque</code></li></ul></li> <li><strong>Hash Maps</strong>: <ul><li>Python: <code>dict</code></li> <li>Java: <code>java.util.HashMap</code></li> <li>C++: <code>std::unordered_map</code></li></ul></li> <li><strong>Heaps</strong>: <ul><li>Python: <code>heap</code> module</li> <li>Java: <code>java.util.PriorityQueue</code></li> <li>C++: use <code>std::priority_queue</code></li></ul></li></ul> <p>Other data structures such as graphs, disjoint sets, tries, etc require you to implement them yourself. You must know how to use these data structures, especially for questions that ask you to extend the normal functionality of these data structures.</p> <h3 id="the-hackerrank"><a href="#the-hackerrank">The HackerRank</a></h3> <p>To succeed in the HackerRank round, you must fulfil their unknown criteria. For each question, there are typically test cases, visible and hidden. The objective is normally to clear as many test cases as you can (while also getting a submission that doesn’t exceed the time limit), however, some companies are known to prefer people who quickly finish the assessment. Alternatively, you may not even solve any of the test cases, but an engineer may later look at your code and progress you to the next round. Ensure you have a look over every question and never spend too much time on one problem if you can’t make progress.</p> <p>Companies may also add multiple-choice questions on topics such as data science or computer hardware fundamentals, which is more frequent in data-adjacent roles but can also appear in coding tests, so be prepared.</p> <p><!--[-1--><img src="/assets/guide-to-tech/proctoring.PNG" alt="/assets/guide-to-tech/proctoring.PNG" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>The HackerRank environment <a href="https://support.hackerrank.com/hc/en-us/articles/360011479133-Proctoring-HackerRank-Tests" rel="nofollow noopener noreferrer external" target="_blank">typically monitors whether you tab out</a>, along with any other potential interactions outside the browser, though not every company cares about whether you do this.</p> <h3 id="companies-that-use-this-assessment"><a href="#companies-that-use-this-assessment">Companies that use this assessment</a></h3> <ul><li>Optiver, IMC, Akuna, SIG, Citadel Securities, and VivCourt all use coding tests in some form to filter out applicants who can’t code in the relevant language.</li> <li>Google, Atlassian, Canva, TikTok, and Amazon are also known for using coding tests early on.</li> <li>NAB and ANZx are known to use coding tests, however this depends on the role.</li> <li>Thales, Telstra, and Xero also employ coding tests, while Quantium employs a coding knowledge quiz</li></ul> <h2 id="psychometric-tests"><a href="#psychometric-tests">Psychometric Tests</a></h2> <p>One of my less preferred assessment items, the psychometric test baffles me. I don’t understand how it gauges much from a candidate, aside from being a time-consuming filter. The components that may be included in a psychometric test often include:</p> <ul><li>Numerical Reasoning</li> <li>Verbal Reasoning</li> <li>Inductive Reasoning</li> <li>Logical Reasoning</li> <li>Personality tests (On a related note I found <a href="https://www.timothyhorrigan.com/documents/unicru-personality-test.answer-key.html" rel="nofollow noopener noreferrer external" target="_blank">an answer key to one sort of personality test</a> )</li></ul> <p>Not much can be said about these tests, and there’s not much I can suggest to prepare for them. They’re relatively basic and are often employed by <strong>the banks</strong>, or other non-tech organisations. Prosple has a <a href="https://au.prosple.com/interviews/top-5-tips-for-surviving-psychometric-testing" rel="nofollow noopener noreferrer external" target="_blank">guide</a> on how to survive a psychometric test and outlines what you may expect from a test. If you feel the need to brush up on this type of test, the <a href="https://www.youtube.com/watch?v=vowwzQx-fGY&amp;list=PLCcteVWYyBts9bff--pGdSAGs8UeExjlF" rel="nofollow noopener noreferrer external" target="_blank">Careervidz’</a> link on the guide covers a variety of questions. You are often allowed a scientific calculator and are recommended to make use of it whenever possible. However, there are more interesting assessments ahead, that test applicants with games as well.</p> <h3 id="esoteric-tests-cognitive-testsgames"><a href="#esoteric-tests-cognitive-testsgames">Esoteric Tests (Cognitive Tests/Games)</a></h3> <p>Zap-N thought it would be funny to turn <a href="https://youtu.be/DtZtbDA1wSY?t=160" rel="nofollow noopener noreferrer external" target="_blank">Cooking Mama</a> into an assessment that tests your reaction time. Or better yet, how about <a href="https://www.youtube.com/watch?v=UcLrdhGBQ9M" rel="nofollow noopener noreferrer external" target="_blank">that game where you can pump it as many times as you want, but you lose if it pops</a>. In case you’re completely lost on what I’m talking about, <strong>Optiver</strong>, <a href="https://www.tiktok.com/@jamesleonidas2/video/7283692043765894442" rel="nofollow noopener noreferrer external" target="_blank">and some other companies</a> use more esoteric assessments such as Grill Master and the Balloon Game to measure your reaction time, how you approach risk tolerance, and so on.</p> <p><!--[-1--><img src="/assets/guide-to-tech/chika.gif" alt="Fujiwara Chika pumping a balloon" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>To me, these assessments are similar to pymetrics assessments, which consist of vague tasks that seem to be easier the more you possess skills that are required for a variety of video games. <a href="https://www.tradinginterview.com/courses/company-preparations-course/lessons/optiver/topic/first-round-zap-n-test/" rel="nofollow noopener noreferrer external" target="_blank">Trading Interview</a> lists some strategies for the balloon popping game, where you should discern around when the balloon pops, and plan accordingly. Grill Master being compared to <a href="https://store.steampowered.com/app/448510/Overcooked/" rel="nofollow noopener noreferrer external" target="_blank">Overcooked</a> should tell you that playing some reaction-based video games would be a good idea. As an aside, these games are reminiscent of flash games, and would not be hard to recreate. A potential side-project could entail recreating these mini-games to practice on.</p> <p>This section will also be updated as I’m informed of any other strange assessment items, though it’s also worth noting anyone applying for a trader role (IMC and Optiver specifically) will likely experience these games at some point. I also consider some of the games you get here to be psychometric testing as well, just in a more unusual form. The <a href="https://humanbenchmark.com/" rel="nofollow noopener noreferrer external" target="_blank">Human Benchmark</a> covers some games that may be similar to what you may find in a pymetrics assessment.</p> <h3 id="companies-that-use-this-assessment-1"><a href="#companies-that-use-this-assessment-1">Companies that use this assessment</a></h3> <p>It would honestly be easier to list the companies that don’t start with psychometric tests… The below list is definitely not exhaustive (like all the other lists).</p> <ul><li>The Big 4 banks (+Macquarie) and accounting firms are known for starting with psychometric tests <ul><li>ANZ has a game-based assessment consisting of 16 games</li></ul></li> <li>Amazon and Xero also incorporate some personality tests in their initial assessments</li> <li>Telstra and Optus use psychometric tests</li> <li>Various government roles also use psychometric tests</li> <li>Optiver is known to utilise Zap-N as part of their software engineer OA</li></ul> <h2 id="one-way-video-interviews-vieple-hirevue"><a href="#one-way-video-interviews-vieple-hirevue">One-way Video Interviews (Vieple, HireVue)</a></h2> <p>A one-way video interview, contrary to its name is an assessment where you’re recorded and analysed based on your responses. Vieple and HireVue are common video interview platforms used, and you’re typically given a set of questions to answer within a certain timeframe. The format starts with a question, along with a grace period to think about an answer, and then you are recorded. Some interviews allow you to be re-recorded. The software allegedly uses AI to recognise facial behaviour and patterns in conjunction with your verbal answers, though I cannot find sources online that corroborate that assessment.</p> <p>My anecdotal advice for overcoming digital video interviews is as follows:</p> <ul><li>Attempt to centre yourself and try to look at the web camera that you’re using</li> <li>Be well-spoken, take your time to put together a response</li> <li>Incorporate keywords about the role in your responses where possible</li> <li>Prepare to be asked technical and behavioural questions</li></ul> <h3 id="companies-that-are-known-to-do-this"><a href="#companies-that-are-known-to-do-this">Companies that are known to do this</a></h3> <ul><li>CBA/ANZ and Big 4 Consulting Firms use a one-way video interview (typically behavioural questions)</li> <li>IMC has a video interview that can consist of technical questions</li> <li>IAG/Optus/Rio Tinto/Car Sales/Leidos/Xero/REA have one-way video interviews</li></ul> <p>With enough luck, you’ll make it to an actual human interview.</p> <h1 id="interviews"><a href="#interviews">Interviews</a></h1> <p>Now we get to the interviews, the more impactful part of the application rounds. You’ll be talking with recruiters, engineers, and managers during these rounds, and will be tasked with demonstrating your skills or experiences to convince the company that you’re fit for the role.</p> <h2 id="recruiter-callphone-screen"><a href="#recruiter-callphone-screen">Recruiter Call/Phone Screen</a></h2> <p>With larger companies, the first human contact you’ll arrive at is the talent acquisition team, or in other words, the recruiter who’ll guide you through the process and give you updates on your progression. The recruiter round is usually known as a phone screen (though it’s usually a Zoom call nowadays). The recruiter call serves as an opportunity for the recruiter to get a better understanding of you as a candidate, but also works the other way around; you should use the opportunity to learn more about the company. It’s worth noting that in some cases, you may be interviewing with an engineer, but it’s much more common to talk with a recruiter first.</p> <ul><li><strong>What can you be asked?</strong> <ul><li>Basic behavioural questions, see the behavioural round for more info</li> <li>Technical trivia specific to the role</li> <li>General Computer Science Fundamentals (Data structures)</li> <li>Coding Fundamentals (Language Specific features)</li></ul></li> <li><strong>What should you ask?</strong> <ul><li>How many rounds there are, how to prepare for them</li> <li>What the role entails, what you may be working on</li> <li>Company culture</li> <li>Any other questions you have about the company</li></ul></li></ul> <p>The call is also used to confirm logistical details, such as when you graduate, whether you have any exploding offers, or are applying to any other places. If you’re asked behavioural questions, see the Behavioural Interview section for more information. The technical trivia asked can include computer science fundamentals, computer hardware information, or role-specific concepts. If you can’t answer them, preface that and give your best understanding of the concept. In the case that the phone screen you’ve received is technical, see the Technical Interviews section.</p> <h3 id="companies-with-this-round"><a href="#companies-with-this-round">Companies with this round</a></h3> <p>This round can take on various forms and will vary from company to company.</p> <ul><li>Atlassian and Canva incorporate a recruiter round with technical trivia and behavioural questions</li> <li>IMC and Optiver have a short behavioural round with a recruiter</li></ul> <h2 id="technical-interviews"><a href="#technical-interviews">Technical Interviews</a></h2> <p>Ah, the technical interview. <a href="https://www.youtube.com/watch?v=ubOhA56G_tk" rel="nofollow noopener noreferrer external" target="_blank">Likened to surviving a gruelling series of enhanced interrogation techniques</a>, the technical interview is often seen as the true filter of getting a software engineering job. Nonetheless, we press on. It’s worth noting that technical interviews are less common in Australia since they’re more focused on hiring someone with the right mentality that they can train up, though companies in search of top talent can afford to be pickier. The big tech companies and HFTs are known for these rounds, and is important to prepare for them so that you’re not caught unawares when you’re thrown a Leetcode medium to solve in front of your interviewers.</p> <p>Mock technical interviews are your best friend when it comes to technical interview practice. Take questions from the resources in the HackerRank question and work with a friend to solve them under interview conditions. There are plenty of opportunities to attempt mock interviews; your university society may run mock technical interview events, Discord servers that run various interview preparation sessions, dedicated study programs such as <a href="https://www.youtube.com/watch?v=DBeklgUv1Rg" rel="nofollow noopener noreferrer external" target="_blank">Ravi’s Study Program</a>, or asking your friends to mock interview you. The more you practice, the more familiar and confident you become with the process.</p> <h3 id="navigating-the-interview"><a href="#navigating-the-interview">Navigating the Interview</a></h3> <p>To demonstrate that you’re an ideal candidate in the technical interview, you’ll want to demonstrate in detail that you can write code, problem-solve, and communicate with your interviewer. There are templates for how you should conduct the technical interview; <a href="https://medium.com/@sarahscode/reacto-technical-interview-prep-the-fullstack-way-706929a44e90" rel="nofollow noopener noreferrer external" target="_blank">REACTO</a> comes to mind, or the practices outlined in the <a href="https://www.techinterviewhandbook.org/coding-interview-cheatsheet/" rel="nofollow noopener noreferrer external" target="_blank">Tech Interview Handbook</a>.</p> <h4 id="start-of-the-interview"><a href="#start-of-the-interview">Start of the Interview</a></h4> <p>Ensure you introduce yourself! Keep it to the point. The interviewer(s) will introduce themselves, and then go over the question. You may have access to your text editor, Google Docs, or an online text editor such as CodePair; it would be a good idea to take down notes while they’re going through the question. After they’ve finished it, you can choose to describe the question as you understood it back to the interviewer to clarify and ensure you’ve understood the question properly. Now, start asking questions about the problem you’ve been presented with, doing so indicates your communication skills and ability to request specific information. This could include questions such as:</p> <ul><li>Assumptions about the input, will you need to deal with edge cases or invalid inputs</li> <li>How large the input is (which could give you hints about the approach you’ll need)</li> <li>Does time complexity matter for a first pass?</li></ul> <p>Once you’ve got a good idea of what the question is, attempt an example test case by hand to communicate that you know what you’re doing.</p> <h4 id="coding-a-solution"><a href="#coding-a-solution">Coding a Solution</a></h4> <p>Before you begin writing code, start with pseudocode to describe your thought process. This could be as text, or it could be verbal, though I recommend writing it down so you can reference it when writing it. You may want to describe any pre-processing on the input, any data structures you may need, or any algorithms or techniques that solve the problem. If you’re confident, you may also describe the time and space complexity of the algorithm you have in mind, though you can also defer that to after you’ve written the code. Once you’re satisfied with your approach, ask the interviewer if you can start coding.</p> <p>Now we get to writing the code. Because you’re working with an interviewer, you’ll need to explain your thought process as you’re coding up a solution. Writing code while speaking code takes conscious effort, and it’s alright to initially suck at it, that’s what practice is for. You can choose to describe what you’ve done before, or after you’ve written some logic if talking while coding proves to be strenuous. Describe the logic you’re writing at a high level, what it intends to accomplish, clarify why you’ve chosen to do it and take your time while doing so. When it comes to coding practice, ensure you use descriptive variable names while you write code that is clean and easy to read. The interviewer is your friend here, they’ll need to be able to read your code if you get stuck down the line.</p> <h4 id="code-review"><a href="#code-review">Code Review</a></h4> <p>After you’ve coded up a solution you’re satisfied with, have a look back on your code, and scan for any immediate mistakes. You can take a test case and simulate the execution of the code to sanity-check your work. Afterwards, have a look at the constraints, and see if you can come up with any edge cases that potentially break your solution. If you’re satisfied that your solution is sound, analyse the space and time complexity if you haven’t already done so. Finally, ask the interviewer if you can test the code. If your code runs successfully, well done! You can talk about optimising your code, and repeat the process above, focusing on refactoring your code as necessary. If your code doesn’t work, or if you’re not sure about how to solve the problem, the interviewer can give you a nudge, which is a key signal to see how you work with other engineers.</p> <p>After you’re finished with the problem, you may be left with some time to ask questions. Come prepared with questions you want to know; this is commonly known as a reverse interview question. Once again, <a href="https://www.techinterviewhandbook.org/final-questions/" rel="nofollow noopener noreferrer external" target="_blank">the Tech Interview Handbook</a> has an extensive list of questions that you may want to ask, however, you should ideally ask questions that you’d be interested in hearing about, as opposed to doing so out of obligation.</p> <h3 id="the-rubric"><a href="#the-rubric">The Rubric</a></h3> <p>Many companies use a general rubric for scoring your performance in an interview. The <a href="https://www.techinterviewhandbook.org/coding-interview-rubrics/" rel="nofollow noopener noreferrer external" target="_blank">Tech Interview Handbook</a> goes into more detail about what this rubric looks like at different companies. In general, you can expect to be assessed across the following criteria:</p> <ul><li>Communication: How well you work with the interviewer, ask for clarification, and explain your thought process while solving the problem</li> <li>Technical Competency: Does the code work, are there syntax errors, etc</li> <li>Problem Solving: Do they solve the problem, and is the approach optimal?</li></ul> <p>These criteria may not be weighted equally; sometimes the ability to communicate an approach and describe the time/space complexity is more important than having a working solution. <a href="https://old.reddit.com/r/leetcode/comments/1aydvac/what_is_the_mindset_of_meta_interviewers/kruj9mg/" rel="nofollow noopener noreferrer external" target="_blank">This Reddit thread</a> covers a rubric for a company where even if you get a solution that doesn’t work, being able to communicate still gets you quite a way. The scores for a rubric are commonly from the set of values <span class="math math-inline"><!----><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><mn>1</mn><mo separator="true">,</mo><mn>2</mn><mo separator="true">,</mo><mn>3</mn><mo separator="true">,</mo><mn>4</mn><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\{1,2,3,4\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut"></span><span class="mopen">{</span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">3</span><span class="mpunct">,</span><span class="mspace"></span><span class="mord">4</span><span class="mclose">}</span></span></span></span><!----></span> (though different companies may use their own scoring scale), and they roughly translate to being a “strong no hire” to a “strong hire”. All of these scores are then combined with the scores of other final interviews, and then a hiring committee decides whether you make it in or not. For more information on what a potential “strong hire” looks like, have a look at the <a href="https://www.techinterviewhandbook.org/coding-interview-rubrics/" rel="nofollow noopener noreferrer external" target="_blank">Tech Interview Handbook</a>, specifically the section on the detailed explanation of each evaluated criteria, and incorporate them in future interviews.</p> <h3 id="other-tips"><a href="#other-tips">Other Tips</a></h3> <p>The technical interview is not just about how well you solve the presented problem, or how elegant your code is, but also functions as a behavioural interview. The way you interact with your interviewer is akin to a pair coding session; that is, you can talk the process through with them and rubber-ducky debug your work. If you’re also stuck with the problem, your interviewer may suggest an alternative line of thinking to put you back on track; seeing how you interact with the interviewer is also another aspect of the process.</p> <h3 id="companies-with-this-round-1"><a href="#companies-with-this-round-1">Companies with this round</a></h3> <ul><li>Every quantitative trading firm has at least one technical interview</li> <li>Google/Canva/Atlassian/TikTok/Amazon/Snap/Airwallex/AfterPay all have at least one technical interview</li></ul> <h2 id="system-design-interviews"><a href="#system-design-interviews">System Design Interviews</a></h2> <p>The System Design interview is not very common at an intern level, often appearing in interviews for experienced hires or for some graduate programs, but it doesn’t hurt to have a decent idea of how you’d design a system at a high level. These interviews can involve whiteboarding/diagramming as opposed to coding, as the round relies more on your knowledge. If you want an idea of what an exaggerated version of the interview looks like, Krazam’s <a href="https://www.youtube.com/watch?v=y8OnoxKotPQ" rel="nofollow noopener noreferrer external" target="_blank">Microservices</a> video is a fun watch.</p> <p>My personal recommendations include:</p> <ul><li><a href="https://www.designgurus.io/course/grokking-the-system-design-interview" rel="nofollow noopener noreferrer external" target="_blank">Grokking the System Design Interview (available on LibGen)</a></li> <li><a href="https://github.com/donnemartin/system-design-primer" rel="nofollow noopener noreferrer external" target="_blank">System Design Primer</a></li> <li><a href="https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/" rel="nofollow noopener noreferrer external" target="_blank">Designing Data Intensive Applications</a> (may be overkill for a beginner)</li> <li>The <a href="https://www.youtube.com/watch?v=NtMvNh0WFVM" rel="nofollow noopener noreferrer external" target="_blank">Exponent Youtube channel</a></li> <li><a href="https://www.youtube.com/watch?v=JIbIYCM48to" rel="nofollow noopener noreferrer external" target="_blank">Top 50+ AWS Services Explained in 10 Minutes</a></li></ul> <p>It’s worth reiterating that you most likely will not receive a system design question at the level of the Exponent interviews, but the general domain knowledge that comes from listening to the videos is useful. As an example, I’ve been asked to whiteboard a system for assigning tags to cards, which involves defining endpoints for the API, and how the databases store data, then moving onto topics such as the CAP theorem, scaling vertically, and horizontally.</p> <h3 id="companies-with-this-round-2"><a href="#companies-with-this-round-2">Companies with this round</a></h3> <p>You can expect to see some form of system design at Optiver, TikTok (team-dependent), and other big tech companies. Some companies may be interested in how your system scales, while other companies care about latency and low-level specifics.</p> <h2 id="behavioural-interviews"><a href="#behavioural-interviews">Behavioural Interviews</a></h2> <p>The behavioural interview is effectively a culture fit round, to see if you’re capable of working with other people and aligning with the company’s values. You want to pitch your best self, without embellishing the truth beyond what you can justify, while also proving that you’re a culture fit.</p> <h3 id="your-elevator-pitch"><a href="#your-elevator-pitch">Your Elevator Pitch</a></h3> <p>For any interview, you should be able to fire off a concise elevator pitch that portrays your best self. I typically begin with my name, the course I’m studying, the societies I’m involved in (and what I do), hobbies (can include job-relevant and non-relevant hobbies), and any relevant job experience I have. This is typically a response to the question “Tell me about yourself”, so you really want to hit it home, why you’d be perfect for the job from the get-go, while also leaving bread crumbs for the interviewer to ask about in more detail. I typically keep the responses to these questions around a minute or two at most, as you’ll have more opportunities to talk about the specifics of what you mentioned later on.</p> <h3 id="star---preparing-stories"><a href="#star---preparing-stories">STAR - Preparing stories</a></h3> <p>The recommended answering strategy for most behavioural questions is STAR. The underlying idea is to tell a story in response to a question about a scenario and reveal the soft skills learned through the story. It stands for:</p> <ul><li>Situation: What was the background, the problem, and why was it a problem?</li> <li>Task: What were you tasked with?</li> <li>Action: What did you do to solve the task?</li> <li>Results: What did your actions lead to? How would you improve upon what you did in the future?</li></ul> <p>The optimal method for preparing stories is to write down your past experiences in a grid and identify the STAR elements in each of them. You don’t need to be able to recite the story in STAR format by heart, but having them written down means you can quickly revise them before an interview, and raise any aspects of the stories you found particularly insightful.</p> <h3 id="company-values"><a href="#company-values">Company Values</a></h3> <p>Many companies have a page dedicated to their company values; it is a good idea to learn these values and bring them up in the interview. In the case of Atlassian, you may be asked what your favourite Atlassian value is, and being prepared will help mitigate any awkwardness while also demonstrating that you did your research going into the interview. If you so desire, you can try intertwining aspects of company values into your responses to questions, and then bring it up afterwards, to demonstrate that you’re aligned with the company values.</p> <h3 id="vibes"><a href="#vibes">Vibes</a></h3> <p>As mentioned before, behavioural interviews attempt to determine whether you’re a cultural fit for the company. Some interviews may grill your responses more, intending to see how you perform under pressure, and if you respond with honesty. Being able to navigate all sorts of challenges during an interview, and being able to adapt to the vibes of a company is a skill that comes with experience in interviews. Be mentally prepared to think on the fly, since you may be given a question you’ve never prepared for or have to justify your reasoning for an answer. If you’re particularly interested in a company, ensure you research what the company does so you can appear informed and knowledgeable in the interview.</p> <h3 id="resources"><a href="#resources">Resources</a></h3> <p>A list of questions from various resources includes:</p> <ul><li>the <a href="https://www.techinterviewhandbook.org/behavioral-interview-rubrics/" rel="nofollow noopener noreferrer external" target="_blank">Tech Interview Handbook on rubrics</a></li> <li>the <a href="https://www.techinterviewhandbook.org/behavioral-interview-questions/" rel="nofollow noopener noreferrer external" target="_blank">Tech Interview Handbook - Behavioural Interview Questions</a></li> <li><a href="https://www.themartec.com/insidelook/behavioral-interview-questions" rel="nofollow noopener noreferrer external" target="_blank">41 Behavioural Interview Questions You Must Know</a></li> <li><a href="https://soulsearch.files.wordpress.com/2007/05/64interviewquestions1.pdf" rel="nofollow noopener noreferrer external" target="_blank">How to Answer the 64 Toughest Interview Questions</a></li></ul> <h3 id="group-activitiesassessment-centre"><a href="#group-activitiesassessment-centre">Group Activities/Assessment Centre</a></h3> <p>Consulting firms and banks are known to utilise assessment centres to assess candidates and how they work with others in group activities. The group activities could include a case study, working in a team to pitch a product, or theoretical scenario exercises to test your ability to cooperate with each other. Resist the urge to shout over each other and try to dominate the conversation; instead, try to work together and set clear expectations about who works on what early on. <a href="https://au.prosple.com/applying/assessment-centres" rel="nofollow noopener noreferrer external" target="_blank">Prosple has a page</a> dedicated towards potential assessment items in the assessment centre.</p> <h3 id="companies-with-this-round-3"><a href="#companies-with-this-round-3">Companies with this round</a></h3> <p>Nearly all companies have a behavioural round somewhere down the line. If there’s no behavioural round, there’s typically an assessment centre, which is a group behavioural round.</p> <h2 id="examples-of-interview-formats"><a href="#examples-of-interview-formats">Examples of Interview Formats</a></h2> <p>I’ve listed some companies and their interview rounds below for reference. Take these examples as a baseline; the interview format is subject to change.</p> <h3 id="example-1---atlassian-2023"><a href="#example-1---atlassian-2023">Example 1 - Atlassian (2023)</a></h3> <p>As an example, Atlassian has four rounds in total. Their internships open in early February and is typically the first big tech company to open their applications. They are open only to penultimate students, and have a range of intern roles including software engineering (front-end and back-end), site reliability, data science, machine learning, product management, and so on. Students must be in their penultimate year to apply for the internship program.</p> <p>The software engineer intern process goes as follows:</p> <ol><li>HackerRank OA consisting of three to five problems (pass X test cases to progress)</li> <li>Recruiter Screen (confirming general details, some trivia, questions about the company)</li> <li>Technical Interview (A round where your live coding and communication skills are put to the test)</li> <li>Values Interview (A behavioural interview to understand how you align with Atlassian’s values)</li></ol> <p>Atlassian used to have a System Design interview, however it was scrapped as many undergraduate students were unfamiliar with the concepts. The graduate version of the interview process has an extra management interview.</p> <h3 id="example-2---optiver-2023"><a href="#example-2---optiver-2023">Example 2 - Optiver (2023)</a></h3> <p>Optiver’s software development internship is one of the few internships available to non-penultimate students, with first-year students being eligible to apply for the program. Intern applications opened at the start of March 2023. Quantitative trading firms are also known for their Superday gauntlets, where you do a set of interviews in a day.</p> <ul><li>An online assessment consisting of <a href="https://www.tradinginterview.com/courses/company-preparations-course/lessons/optiver/topic/first-round-zap-n-test/" rel="nofollow noopener noreferrer external" target="_blank">Overcooked and other various Flash games</a></li> <li>HackerRank OA consists of several problems</li> <li>Behavioural Interview 1</li> <li>Technical Interview (Involves CodePair)</li> <li><strong>A super day consisting of (in no particular order):</strong> <ul><li>Behavioural Interview 2 (described as an interrogation)</li> <li>Object Oriented Design Interview (No code, involves diagramming)</li> <li>Algorithm Design (pseudocode)</li></ul></li></ul> <p>The process has changed for 2024, which incorporates system design.</p> <h3 id="example-3---cba-2022"><a href="#example-3---cba-2022">Example 3 - CBA (2022)</a></h3> <p>Commonwealth Bank (CBA) has technology streams for engineers and data scientists. The internship tends to open around the middle of the year.</p> <ul><li>A 75-minute long psychometric test that consists of basic maths, pattern matching, and personality questions</li> <li>A HireVue consisting of several behavioural questions (One-way video interview)</li> <li>A virtual assessment centre consisting of: <ul><li>Four 15-minute interviews with CBA employees (Consisting of behavioural questions and general opportunities to ask about the company)</li> <li>A group activity with two other applicants (Given an idea or product, work in a team to pitch it)</li></ul></li></ul> <p>The graduate process is identical to the intern process, to my knowledge.</p> <h3 id="example-4---canva-2023"><a href="#example-4---canva-2023">Example 4 - Canva (2023)</a></h3> <p>Canva hires engineers in frontend, backend, infrastructure, security, and machine learning. Each of the processes has a similar structure but has specialisation-specific questions. Students must be in their penultimate year of study to apply.</p> <ul><li>HackerRank that can only be done in Java/Javascript, depending on your specialisation</li> <li>Recruiter interview that consists of behavioural questions and specialisation-specific technical trivia</li> <li>Technical Interview with specialisation-specific tasks (e.g building an application using JS/HTML/CSS or a Leetcode problem in Java)</li></ul> <h3 id="example-5---imc-2024"><a href="#example-5---imc-2024">Example 5 - IMC (2024)</a></h3> <p>IMC (International Market Makers Combination) is another Dutch quantitative trading firm that hires software engineer interns in their penultimate year. They open around February.</p> <ul><li>A HackerRank that can be done in Java/C/C++</li> <li>A Vieple (one-way interview) consisting of technical questions</li> <li>A behavioural phone interview</li> <li>A super day consisting of: <ul><li>A technical round</li> <li>A behavioural round</li></ul></li></ul> <p>IMC is also known for flying candidates to the office in Sydney for a visit if they reach the final super day round, however, I cannot confirm if this is still the case.</p> <h2 id="where-to-from-here"><a href="#where-to-from-here">Where to from here?</a></h2> <p>So you’re done with your interviews; now what? Resist the urge to let the potential outcome swarm your mind. If you have more interviews, focus on preparing for them, while keeping up with any coursework, and your daily life. Depending on the company, you may know within the next week, all the way up to a month later. I recommend reflecting on how you went in each interview; that way you can quickly identify areas to improve upon when given feedback.</p> <h3 id="failure"><a href="#failure">Failure</a></h3> <p>Failure is very common at an intern/graduate level; this is unfortunately because there are too many applicants to interview and too few roles for everyone. You shouldn’t take it personally if you’re rejected from a place, or many places, it’s just a natural aspect of interviewing. Rejections build resilience, and you’ll get a better idea of how to interview effectively each time till you finally get where you want. In my case, I got rejected from a place after a month of doing a final interview with no feedback, and later found an even better opportunity. There’s always another place, and another year if you don’t get in this time.</p> <h3 id="tackling-applications"><a href="#tackling-applications">Tackling Applications</a></h3> <p>When it comes to applying to companies, apply early on, and keep track of your applications so that you don’t forget when you have an interview. Planning ahead and having dates down will counteract your surprise when you have five interviews in a week, along with regular coursework. When it comes to scheduling interviews, don’t feel urged to book your interviews ASAP, take your time and space them apart so you’re not bombarded with the same song and dance. And finally, ensure you get some mock interview practice before you start interviewing, so you’re not out of practice and caught off guard when it counts.</p> <h3 id="places-to-practice"><a href="#places-to-practice">Places to Practice</a></h3> <p>Practice, practice, practice! I cannot stress how important it is to do mock interviews with your friends or people in the industry. The best practice is the real thing, which is why I usually advise applying everywhere and using places that you’re not as invested in as practice runs for the roles you’re gunning for. Below are some places (in no particular order) you can look to find people to prepare with.</p> <ul><li><a href="https://www.pramp.com/#/" rel="nofollow noopener noreferrer external" target="_blank">Pramp</a> (Worth noting that sometimes your interviewer may not show up)</li> <li><a href="https://interviewing.io" rel="nofollow noopener noreferrer external" target="_blank">interviewing.io</a></li> <li>Ravi’s Study Program - As a whole, this is a <strong>free</strong> boot camp that gets your technical and behavioural skills up to scratch. The program is a good way of keeping yourself accountable, and the people involved are passionate about it.</li> <li>Your local university society</li> <li>Your friends</li> <li>Random people on the right Discord servers such as <a href="https://discord.gg/mmrQxzDSC8" rel="nofollow noopener noreferrer external" target="_blank">AusDevs 2.0.0</a></li></ul> <h3 id="assorted-interview-resources"><a href="#assorted-interview-resources">Assorted Interview Resources</a></h3> <p>There are countless really amazing interview guides on the internet, the guide I have written is not particularly special compared to some of the sites listed below which go into more detail on the whole process.</p> <ul><li><a href="https://www.techinterviewhandbook.org/software-engineering-interview-guide/" rel="nofollow noopener noreferrer external" target="_blank">The Tech Interview Handbook</a></li> <li><a href="https://interviewing.io" rel="nofollow noopener noreferrer external" target="_blank">interviewing.io</a>, has a range of videos and guides if you scroll to the bottom of the page</li> <li>Cracking the Coding Interview - while it may be on the older end, it has a lot of advice for the entire process, and I absolutely recommend reading it.</li></ul> <h2 id="conclusion"><a href="#conclusion">Conclusion</a></h2> <p>This concludes the numbered entries of my series, which are aimed at providing you with all the resources you need to prepare for internships. It’s a joy to finally be able to finish this series. To put it into perspective, this series is longer than my honours thesis (roughly 12,000 words), and contains my countless observations about the whole process, along with wisdom I’ve gathered from many, many people.</p> <h3 id="acknowledgements"><a href="#acknowledgements">Acknowledgements</a></h3> <p>This was a MASSIVE undertaking, and I’ve basically poured away many hours of my life <del>which could have been spent on Persona 3 Reload</del> on this project. However, I want to acknowledge the many people who’ve helped with the creation of these articles, both indirectly and directly.</p> <ul><li>The Monash Association of Coding, committees past, present and future. Most of my knowledge, and drive to record all this information and make it accessible came from MAC.</li> <li>My friends in the HFT and Big Tech space, who’ve told me about their journey and what worked for them. <ul><li>In particular, Josh, Lauren, Indra, William, Jim, Madison, Eric J, Sung Ho, Alex M, and Nick L, all of you have helped shape part of this series in one way or another.</li></ul></li> <li>The AusDevs server, for being a massive hub of information that has helped shape this article in particular.</li></ul> <p>Thank you so much for reading till the end! My final words to anyone who doesn’t feel they’re ready for an internship would be the line from Spider-Man: Into the Spider-Verse. <a href="https://youtu.be/BmFbczWrVUw?t=184" rel="nofollow noopener noreferrer external" target="_blank">“When will I know I’m ready? You won’t, it’s a leap of faith.”</a> Good luck with your journey.</p> <p><!--[-1--><img src="/assets/guide-to-tech/spiderman-when.gif" alt="/assets/guide-to-tech/spiderman-when.gif" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="university" scheme="https://https:///?tags=university" />
    <category term="career" scheme="https://https:///?tags=career" />
    <category term="playbook" scheme="https://https:///?tags=playbook" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Year in review - 2023]]></title>
    <link href="https://https:///2024-update" />
    <id>https://https:///2024-update</id>
    <published>2024-01-15T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.139Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h1 id="the-year-in-review"><a href="#the-year-in-review">The year in review</a></h1> <p>2023 was an extraordinary year by all accounts, and I’d never have expected such an eventful final year during my time at Monash. 2023 seemed to be the antithesis of my first year in 2020, where the whole year was plagued by the Victorian lockdown, which turned the year into a fever dream. So, where do we start?</p> <h2 id="my-internship-at-canva"><a href="#my-internship-at-canva">My Internship at Canva</a></h2> <p>To this date, I still can’t believe I ended up interning at Canva.  The experience was incredibly fun, and eye-opening, as I was working with many engineers and scientists on Canva’s Text to Image product. I intend to talk more about my internship in a future post, but I was given a research project relating to Image AI, and investigating various issues, such as <a href="https://www.bloomberg.com/graphics/2023-generative-ai-bias/" rel="nofollow noopener noreferrer external" target="_blank">bias in Generative AI models</a>. The research work was extremely fun, and despite being open-ended, I discovered novel mitigation approaches for Text to Image models that I would later go on to research. I ended up receiving a return offer, and I’ll be returning soon as a full-time Machine Learning Engineer.</p> <h2 id="president-of-mac"><a href="#president-of-mac">President of MAC</a></h2> <p>My term as president of the <a href="https://monashcoding.com" rel="nofollow noopener noreferrer external" target="_blank">Monash Association of Coding</a> was stable and strong as we hit over 1000 members at the end of the term, which is in the category of Monash’s largest clubs. Our <a href="https://www.instagram.com/reel/CrdNYd0sRf6/" rel="nofollow noopener noreferrer external" target="_blank">Technology Careers Evening</a> had more people and sponsors while being cheaper to run, and our <a href="https://www.instagram.com/reel/Cxcy-JUSmNu/" rel="nofollow noopener noreferrer external" target="_blank">MACathon</a> had over 100 participants. One of my favourite things about the club was the Instagram reels made by the content creation team, which were really funny, and captured the events really well. So well, <a href="https://www.instagram.com/reel/Cxp5F7PyDRx/" rel="nofollow noopener noreferrer external" target="_blank">that one of the reels</a> got over 60,000 views… While I have some regrets about my time as president and not getting to talk to everyone, I can rest easy, knowing that the club will thrive under its new leadership and a new IT scene.</p> <p><!--[-1--><img src="/assets/update/mac2023.jpg" alt="/assets/update/mac2023.jpg" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>Cya MAC. It’s been a great three years.</p> <h2 id="an-unforgettable-saga"><a href="#an-unforgettable-saga">An Unforgettable Saga</a></h2> <p>There were some other major events, that I will write about, in later articles. However, it ends with me dressed as a purple Teletubby at the end of the WIRED EGM, with my friend’s election as President of WIRED. This could only be summarised as a massive movement within the IT community at Monash, that ended with a lot of people rallying behind one person, in the hopes of seeing a complete WIRED, and one that could unite all the IT student teams and clubs. A person from Monash called Nhan <a href="https://nhtnhanbn.github.io/wired" rel="nofollow noopener noreferrer external" target="_blank">has a high-level summary of the events leading up to this crazy end</a>, and someday, I’ll talk about my side of the story as the president of MAC. It is my hope, that with groups of dedicated people, Monash may flourish with an abundance of student resources, produced by the student community. A frustration of mine was that while I often had the idea to do something, it often required a lot of coordination or many resources, and with a better club scene, many students would benefit from these resources.</p> <h2 id="this-site"><a href="#this-site">This site</a></h2> <p>I spent way too much time on writing, whether it’s my honours thesis, or writing the equivalent of a thesis with my playbook series. This year, I’d like to finish part three soon before internship applications open and resume documenting the Neochomp, as it was a very fulfilling project with my friend <a href="https://whether-weather.com/" rel="nofollow noopener noreferrer external" target="_blank">Shin</a>. Eventually, I’d also like to write about my time at university, as I think the whole experience, starting in 2020 was a very eventful journey.</p> <p><!--[-1--><img src="/assets/update/wtf.png" alt="/assets/update/wtf.png" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>Something that came to me…</p> <h2 id="my-honours-year"><a href="#my-honours-year">My honours year</a></h2> <p>My honours year in Applied Data Science was very interesting; only three students were taking the honours year. The first semester consisted of seminars with academics on their research, along with morning tea, while we’d discuss various machine learning papers, and as part of a reading club. The second semester was focused on the compilation of my thesis, which was a continuation of my research at Canva. The thesis is titled <a href="https://www.saikumarmk.com/assets/honours_thesis.pdf" rel="nofollow noopener noreferrer external" target="_blank">“Bias Modelling and Mitigation in Diffusion Models”</a> and covers a novel approach to increasing the diversity in gender and appearance of people in Diffusion-based image generation models. The work was interesting, and I really enjoyed the research but felt that the scope of an honours thesis was too short for the topic, as I had an urge to continue the work, potentially in the form of a PhD.</p> <h2 id="fun-at-siggraph-asia-sydney"><a href="#fun-at-siggraph-asia-sydney">Fun at SIGGRAPH Asia Sydney</a></h2> <p>Towards the second half of the year, Canva reached out to ask if I would be interested in being a speaker for a panel at <a href="https://asia.siggraph.org/2023/" rel="nofollow noopener noreferrer external" target="_blank">SIGGRAPH Asia 2023</a> which was hosted in Sydney. Seeing as flights, and accommodation were provided on top of a full-access ticket, I decided to take the short vacation to Sydney.</p> <p><!--[-1--><img src="/assets/update/siggraph.webp" alt="/assets/update/siggraph.webp" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>Overall, the experience was very eye-opening; I had the chance to network with people across companies such as Nvidia, Pixar, ILM, and seasoned software engineers with decades of experience. VFX studios use machine learning for animation, which was exciting to learn about, especially for software like RenderMan.</p> <h2 id="where-to-from-here"><a href="#where-to-from-here">Where to from here?</a></h2> <p>Hopefully, I’ll be able to pump out the articles I have in mind, and somehow cope with full-time work. Who knows. I expect things will be much more calm this year.</p><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="update" scheme="https://https:///?tags=update" />
  </entry>
  <entry>
    <title type="html"><![CDATA[A Universe of Units - An exploration into Monash Handbook Scraping]]></title>
    <link href="https://https:///universe-of-units" />
    <id>https://https:///universe-of-units</id>
    <published>2023-11-03T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h1 id="introduction"><a href="#introduction">Introduction</a></h1> <p>You may have seen the unit graph visualisations on my website and wondered what they mean or how I came to create them. The <a href="https://saikumarmk.github.io/monash-handbook-plus/graph" rel="nofollow noopener noreferrer external" target="_blank">Monash Unit Graph</a> visualises all ~5200 units offered at Monash University across all campuses. But how did I come to collect all this data? This piece will outline the format of the Monash handbook, how to scrape the handbook, how to collect requisites, and how to put all the information together.</p> <h2 id="inspirations"><a href="#inspirations">Inspirations</a></h2> <p>The idea for scraping the Monash Handbook comes from several places, but specifically, representing course requisites as a graph came from the <a href="https://leetcode.com/problems/course-schedule/" rel="nofollow noopener noreferrer external" target="_blank">Leetcode Problem: Course Schedule</a>, where you do a topological sort on the dependency graph to determine if all the courses can be finished. From this simple problem, the idea for automated course planning would arise naturally, adding complexity in the form of different teaching periods, more involved requisites like credit points, and theoretically optimising the time elapsed for a course. A network of units is also a fascinating visualisation. My inspiration for the unit graph also draws from the <a href="https://rhumbl.com/examples/curriculum-maps" rel="nofollow noopener noreferrer external" target="_blank">MIT OCW curriculum network</a>, which organises units by the department that runs them, connects units by prerequisites, providing an idea of where a unit may lead you after it’s completed.</p> <p>CSESOC also has a comprehensive course planner named <a href="https://circles.csesoc.app" rel="nofollow noopener noreferrer external" target="_blank">Circles</a> that features a detailed handbook, term planner, and progression checker. It is student-maintained, and the ability to find units you can do after taking a set of units is beneficial for deciding what you should study for an elective.</p> <p><!--[-1--><img src="/assets/universe-units/csesoc-circles-1.PNG" alt="CSESOC Circles" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>Very useful! Very friendly!</p> <h2 id="the-state-of-the-monash-handbook"><a href="#the-state-of-the-monash-handbook">The State of the Monash Handbook</a></h2> <p>And so, that brings us to the pitiful state of the Monash Handbook. Some units have clearly defined requisites that have actual container boxes, such as <a href="https://handbook.monash.edu/current/units/MTH2032" rel="nofollow noopener noreferrer external" target="_blank">MTH2032</a>, while other units are an absolute nightmare, like <a href="https://handbook.monash.edu/current/units/FIT3047" rel="nofollow noopener noreferrer external" target="_blank">FIT3047</a> with the fantastic enrolment rule description you see below.</p> <p><!--[-1--><img src="/assets/universe-units/monash-handbook-1.PNG" alt="FIT3047" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>It’s impossible to turn these text descriptions into a list of rules without relying on a GPT-like language model. We’ll grab requisites in a bit, but there’s a trove of valuable information on a handbook entry. For instance, the student contribution amount (SCA) band is listed, which lets you determine the price of a unit. Why Monash doesn’t display their prices like <a href="https://www.handbook.unsw.edu.au/undergraduate/courses/2024/COMP1521?year=2024" rel="nofollow noopener noreferrer external" target="_blank">UNSW does</a> is beyond me, but I’ve found that some students get surprised that units like <a href="https://handbook.monash.edu/2024/units/FIT2002?year=2024" rel="nofollow noopener noreferrer external" target="_blank">FIT2002</a> costs the same as a commerce unit does typically, which is not ideal. The unit offerings are also listed, which include the teaching period and semester of the unit, learning outcomes, and assessments.</p> <h2 id="scraping-the-handbook-old-version"><a href="#scraping-the-handbook-old-version">Scraping the Handbook (old version)</a></h2> <p>For reference, I had planned to write this article at the start of the year, but I got busy. During this year, Monash updated their handbook and broke the API I used for scraping, making it much harder. Previous work on scraping can be found at <a href="https://github.com/monashcoding/TheBetterHandbookAPI" rel="nofollow noopener noreferrer external" target="_blank">monashcoding/TheBetterHandbookAPI</a>.</p> <p>Monash uses a system called <a href="https://courseloop.com/" rel="nofollow noopener noreferrer external" target="_blank">CourseLoop</a>, which is a curriculum management system. UNSW, Macquarie, La Trobe and other Australian universities also use this system. Previously, you could <code>POST</code> the link <code>https://handbook.monash.edu/api/es/search</code> with a query that looked something like this:</p> <!----><pre class="shiki monokai" json="true"><div class="language-id">json</div><div class='code-container'><code><div class='line'>&#123;</div><div class='line'>"query": &#123;</div><div class='line'>    "bool": &#123;</div><div class='line'>        "must": [</div><div class='line'>            &#123;"query_string": &#123;"query": "monash2_psubject.code: &#123;content&#125;"&#125;&#125;,</div><div class='line'>            &#123;"term": &#123;"live": true&#125;&#125;,</div><div class='line'>        ]</div><div class='line'>    &#125;</div><div class='line'>&#125;,</div><div class='line'>"aggs": &#123;</div><div class='line'>    "implementationYear": &#123;</div><div class='line'>        "terms": &#123;</div><div class='line'>            "field": "monash2_psubject.implementationYear_dotraw",</div><div class='line'>            "size": 100</div><div class='line'>        &#125;</div><div class='line'>    &#125;,</div><div class='line'>    "availableInYears": &#123;</div><div class='line'>        "terms": &#123;"field": "monash2_psubject.availableInYears_dotraw", "size": 100&#125;</div><div class='line'>    &#125;,</div><div class='line'>&#125;,</div><div class='line'>"size": 100,</div><div class='line'>"_source": &#123;</div><div class='line'>    "includes": ["versionNumber", "availableInYears", "implementationYear"]</div><div class='line'>&#125;,</div><div class='line'>&#125;</div></code></div></pre><!----> <p>You could hit the endpoint once for all 5200 Monash units and get all the information in one go. You could also query the UNSW handbook with an identical query and get Monash units from the UNSW Handbook. From here, you can scrape out the details on a page and then serve it as you see fit.</p> <h2 id="scraping-the-handbook-new-version"><a href="#scraping-the-handbook-new-version">Scraping the Handbook (new version)</a></h2> <p>Due to the change in the API for the Monash Handbook site, we can no longer <code>POST</code> the previously mentioned endpoint. When searching for a unit, only the unit name is returned, and looking at the unit entry for a page doesn’t show where the data comes from since JS scripts are used to render the page. Nonetheless, by switching the year for a unit, we find a <code>GET</code> request to <code>https://handbook.monash.edu/_next/data/1F6sQtV9SmVrQtVZjV3Zh/2023/units/MTH2140.json?year=2024</code>. The data provided is identical to the request from the old version but is slightly more formatted. We construct an index with the following request:</p> <!----><pre class="shiki monokai" go="true"><div class="language-id">go</div><div class='code-container'><code><div class='line'>http.Get("https://api-ap-southeast-2.prod.courseloop.com/publisher/search-all?from=0&query=&searchType=advanced&siteId=monash-prod-pres&siteYear=current&size=7000")</div><div class='line'></div></code></div></pre><!----> <p>Unfortunately, we must also request each unit individually, and the server rate limits you. Requesting 1000 units will get you rate-limited for 5 minutes. Since Python sucks at all things concurrency, I decided to use Go. This statically typed language has a focus on concurrency. With rate-limiting and 1000 requests taking around 50 seconds, we can retrieve all the content in less than an hour, much longer than our old approach but still more reasonable than manually scraping the HTML from each page.</p> <!----><pre class="shiki monokai" go="true"><div class="language-id">go</div><div class='code-container'><code><div class='line'>func getContent(item string, category string, results chan map[string]interface&#123;&#125;, </div><div class='line'>                                    failures chan string, rate_limited chan string) &#123;</div><div class='line'>    response, err := http.Get(BASE_LINK + category + "/" + item + ".json?year=current")</div><div class='line'></div><div class='line'>    if err != nil &#123;</div><div class='line'>        results &lt;- nil</div><div class='line'>        failures &lt;- item</div><div class='line'>        return</div><div class='line'>    &#125;</div><div class='line'>    defer response.Body.Close()</div><div class='line'></div><div class='line'>    var data map[string]interface&#123;&#125;</div><div class='line'>    decoder := json.NewDecoder(response.Body)</div><div class='line'>    if err := decoder.Decode(&data); err != nil &#123;</div><div class='line'>        results &lt;- nil</div><div class='line'>        failures &lt;- item</div><div class='line'>        return</div><div class='line'>    &#125;</div><div class='line'></div><div class='line'>    if _, ok := data["message"]; ok &#123;</div><div class='line'>        results &lt;- nil</div><div class='line'>        rate_limited &lt;- item</div><div class='line'>        return</div><div class='line'>    &#125;</div><div class='line'></div><div class='line'>    results &lt;- data</div><div class='line'>&#125;</div></code></div></pre><!----> <p>Where <code>BASE_LINK =https://handbook.monash.edu/_next/data/1F6sQtV9SmVrQtVZjV3Zh/current</code>. Go provides channels for concurrent communication that work very intuitively, and we utilise <code>10</code> workers for parallelisation.</p> <!----><pre class="shiki monokai" go="true"><div class="language-id">go</div><div class='code-container'><code><div class='line'></div><div class='line'>var wg sync.WaitGroup</div><div class='line'>var existingData []map[string]interface&#123;&#125;</div><div class='line'>var failedList []string</div><div class='line'>results := make(chan map[string]interface&#123;&#125;, len(items))</div><div class='line'>failures := make(chan string, len(items))</div><div class='line'>rateLimited := make(chan string, len(items))</div><div class='line'></div><div class='line'>itemsPerWorker := len(items) / numWorkers</div><div class='line'>for idx := 0; idx &lt; numWorkers; idx++ &#123;</div><div class='line'>    start := idx * itemsPerWorker</div><div class='line'>    end := min((idx+1)*itemsPerWorker, len(items))</div><div class='line'></div><div class='line'>    if idx == numWorkers-1 &#123;</div><div class='line'>        end = len(items)</div><div class='line'>    &#125;</div><div class='line'></div><div class='line'>    wg.Add(1)</div><div class='line'></div><div class='line'>    go func(itemsSlice []string) &#123;</div><div class='line'>        defer wg.Done()</div><div class='line'>        for _, item := range itemsSlice &#123;</div><div class='line'>            getContent(item, category, results, failures, rateLimited)</div><div class='line'>        &#125;</div><div class='line'>    &#125;(items[start:end])</div><div class='line'>&#125;</div><div class='line'></div><div class='line'>go func() &#123;</div><div class='line'>    wg.Wait()</div><div class='line'>    close(results)</div><div class='line'>    close(failures)</div><div class='line'>    close(rateLimited)</div><div class='line'></div><div class='line'>&#125;()</div><div class='line'></div><div class='line'></div></code></div></pre><!----> <p>While more verbose, I certainly prefer Go’s approach to concurrency much more than how Python handles it.</p> <h2 id="getting-requisites"><a href="#getting-requisites">Getting Requisites</a></h2> <p>Of course, we still need requisites to turn into a consistent format. While the requisites are sometimes adequately formatted, they only cover a portion of the units, so we need something else. Last year, during our initial work on scraping the handbook, someone noted that MonPlan validates course plans and checks if you can take the units you’ve given. Since you can specify a unit by itself, it will indirectly give you the prerequisites and corequisites needed to enrol in that unit. A <code>POST</code> request is made to <code>https://mscv.apps.monash.edu</code>, the microservice that validates your course plan. With the below JSON request, you can verify your unit plan:</p> <!----><pre class="shiki monokai" json="true"><div class="language-id">json</div><div class='code-container'><code><div class='line'>&#123;</div><div class='line'>"startYear": 2022,</div><div class='line'>"advancedStanding": [</div><div class='line'></div><div class='line'>],</div><div class='line'>"internationalStudent": false,</div><div class='line'>"courseInfo": &#123;</div><div class='line'></div><div class='line'>&#125;,</div><div class='line'>"teachingPeriods": [</div><div class='line'>    &#123;</div><div class='line'>        "year": 2022,</div><div class='line'>        "code": "S1-01",</div><div class='line'>        "units": [</div><div class='line'>                &#123;</div><div class='line'>                    "unitCode": "MTH1030",</div><div class='line'>                    "placeholder": false</div><div class='line'>                &#125; </div><div class='line'>        ],</div><div class='line'>        "intermission": false,</div><div class='line'>        "studyAbroad": false</div><div class='line'>    &#125;</div><div class='line'>]</div><div class='line'>&#125;</div><div class='line'></div></code></div></pre><!----> <p>You can also send 125 units in a course plan before the server rejects your request. You could put 125 units into a semester, and it will attempt to validate the course plan before returning several messages on how invalid your course plan is. From here, we want to look at the message in each response:</p> <!----><pre class="shiki monokai" json="true"><div class="language-id">json</div><div class='code-container'><code><div class='line'>&#123;</div><div class='line'>    "courseErrors": [</div><div class='line'>        &#123;</div><div class='line'>            "description": "Please enrol in 1 of these units: PHR1001",</div><div class='line'>            "level": "error",</div><div class='line'>            "references": [</div><div class='line'>                &#123;</div><div class='line'>                    "teachingPeriodCode": "S1-01",</div><div class='line'>                    "teachingPeriodStartingYear": 2024,</div><div class='line'>                    "unitCode": "PHR3141"</div><div class='line'>                &#125;</div><div class='line'>            ],</div><div class='line'>            "title": "Have not passed enough units",</div><div class='line'>            "type": "UNIT_VERSION_RULES"</div><div class='line'>        &#125;</div><div class='line'>    ]</div><div class='line'>&#125;</div></code></div></pre><!----> <p>So we get an error telling us what our course plan fails on and how to fix it. There are seven different messages:</p> <ul><li><p>Prohibited unit: You’ve enrolled/completed a unit that prevents you from taking the current unit. For example, MTH1030 and ENG1005 both prohibit each other. A thing to note is that you will be given the names of all the prohibited units; with that, e.g. enrolling in ENG1005 and MTH1030 will also tell you that MTH1035 is prohibited</p></li> <li><p>Have not enrolled in a unit: This is unusual, as it only appears for 12 units. It may say to enrol in a list of units; however, it really means to have done it as a prerequisite. EAE2522 is one such example. It has a different format to the below formats. This message also no longer appears on 2024 units.</p></li> <li><p>Have yet to complete enough units: Again, this only appears for 3 units, all of which have the prefix APG. This seems to be a completion requirement.</p></li> <li><p>Have yet to pass enough units: This is the normal message if you lack the prerequisites for a unit. Appears in most places.</p></li> <li><p>Not enough passed credit points: Some units require <code>x</code> credit points before you can enrol in them. Some mandate <code>y</code> credit points from faculty <code>z</code>. This appears less often, but there are 360 occurrences.</p></li> <li><p>Not enough enrolled credit points: Only appears once, but seems to be similar to the above, EDF5019</p></li> <li><p>Missing corequisites: Corequisites are a particular prerequisite that can be taken before you do a unit or concurrently with the unit. For instance, ENG1014 has a corequisite for ENG1005.</p></li> <li><p>Permission is required for this unit: You need to contact someone to enrol. Fairly standard.</p></li></ul> <p>So, we could then represent our requisites as follows:</p> <!----><pre class="shiki monokai" py="true"><div class="language-id">py</div><div class='code-container'><code><div class='line'>class Requisites:</div><div class='line'></div><div class='line'>    prerequisites: list[dict[str]]  # [&#123;'NumReq':int, units:list[str]&#125;, ...]</div><div class='line'>    corequisites: list[dict[str]] # Same as prerequisites</div><div class='line'>    prohibitions: list[str] # [MTH1020, PHS1030...]</div><div class='line'>    permissionRequired: bool </div><div class='line'>    creditPoints: int # 0 by default, 24 for MTH2132 and other special units</div></code></div></pre><!----> <p>Note that prerequisites and corequisites have the exact representation, though they are treated slightly differently in practice. After much data cleaning, we can finally collate our requisites and slot them into our handbook data. There are a few weird prerequisites, such as X credit points of <code>MTH3...</code>, which means any level 3 MTH coded unit, but those are the minority. It’s also worth noting that MonPlan is only partially accurate. It can drop off more complex prerequisites, but that’s for another day.</p> <h2 id="turning-it-into-a-graph"><a href="#turning-it-into-a-graph">Turning it into a graph</a></h2> <p>So, with all this requisite data, we can form our graph by connecting units by prerequisites and corequisites.</p> <!----><pre class="shiki monokai" py="true"><div class="language-id">py</div><div class='code-container'><code><div class='line'></div><div class='line'>nodes = []</div><div class='line'>links = []</div><div class='line'></div><div class='line'>for unit in units_cleaned.values():</div><div class='line'>    # Add unit to nodes list</div><div class='line'>    nodes.append(&#123;"id": unit["code"], "unit_name": unit["title"]&#125;)</div><div class='line'>    </div><div class='line'>    # Iterate over prerequisites</div><div class='line'>    for req in unit.get("requisites", &#123;&#125;).get("prerequisites", []):</div><div class='line'>        for req_unit_code in req["units"]:</div><div class='line'>            if req_unit_code in units_cleaned:</div><div class='line'>                links.append(&#123;"source": req_unit_code, "target": unit["code"]&#125;)</div><div class='line'>            </div><div class='line'>    # Iterate over corequisites</div><div class='line'>    for req in unit.get("requisites", &#123;&#125;).get("corequisites", []):</div><div class='line'>        for req_unit_code in req["units"]:</div><div class='line'>            if req_unit_code in units_cleaned:</div><div class='line'>                links.append(&#123;"source": unit["code"], "target": req_unit_code&#125;)</div><div class='line'></div><div class='line'># Create the final JSON object</div><div class='line'>data = &#123;"nodes": nodes, "links": links&#125;</div></code></div></pre><!----> <p>After that, I use <a href="https://github.com/vasturiano/force-graph" rel="nofollow noopener noreferrer external" target="_blank">force-graph</a> and <a href="https://github.com/vasturiano/3d-force-graph" rel="nofollow noopener noreferrer external" target="_blank">3d-force-graph</a> to render the graph.</p> <h2 id="future-goals"><a href="#future-goals">Future Goals</a></h2> <p>The unit graph I threw together in a few hours is fun but could be more practical due to the number of units on screen. Future works could include local views of selected units to understand what order you should complete units in, what units you can leave till later, or what units you can do from your completed units. More work can be done for automated course planning. I was fascinated with the possibility of cutting down a year of a course under the assumption you had prior credit points, possibly through VCE Algorithmics, University Extension units, or any other source.</p><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="scraping" scheme="https://https:///?tags=scraping" />
    <category term="visualisation" scheme="https://https:///?tags=visualisation" />
  </entry>
  <entry>
    <title type="html"><![CDATA[The Grad/Intern Playbook: Part 2.5 Final Mix - Curating your résumé]]></title>
    <link href="https://https:///guide-to-tech-2.5" />
    <id>https://https:///guide-to-tech-2.5</id>
    <published>2023-06-24T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="introduction"><a href="#introduction">Introduction</a></h2> <p>When it comes to first impressions for your application, it’s nearly always the résumé that gets you to the next round. While the document you pen with all your accomplishments or feats may be an irritating write, I recommend sticking to <a href="https://www.overleaf.com/latex/templates/jakes-resume/syzfjbzwjncs" rel="nofollow noopener noreferrer external" target="_blank">Jake’s Resume</a>, which is written in LaTeX. It’s not particularly time-consuming to learn LaTeX, as you’ll primarily be editing cells with your own entries instead of creating new elements. I also advise against using online Resume makers, as they can take your information and provide resumes that aren’t always optimal. As for the resume looking bland with computer modern, that’s a given, but the format is also straight and to the point. You may find that a more artistic/creative resume works, too; however, I have opted to stick to a resume that delivers information <del>despite having interned at Canva</del>. This article will also be opinionated, so you don’t have to follow every bit of advice listed here. You could undoubtedly adopt another style of resume writing, but this is what has worked for a wide range of people.</p> <p>So, what is the goal of creating a perfect resume? Creating a resume past a point is very subjective, and you should lend yourself to various opinions and adapt the advice of the industry you’re applying to. Our goal here is the tech industry. But there are some key bits of terminology for you to know about.</p> <h3 id="what-recruiters-look-for-the-black-box-problem"><a href="#what-recruiters-look-for-the-black-box-problem">What recruiters look for (The Black Box Problem)</a></h3> <p>A lot of advice you’ll receive is often anecdotal and comes from people who’ve found what works for them. You can ask recruiters what they are looking for. Still, it’s important to note that recruitment can vary across companies, and recruiters can look for different attributes on a resume. As I suggest below, your best option is to aggregate the advice you receive. My frustrations with resumes are how the whole process of recruiting, or at least vetting resumes, can seem like a black box, with the strongest resumes surviving into the next generation but carrying potentially pointless artefacts.</p> <h3 id="the-applicant-tracking-system"><a href="#the-applicant-tracking-system">The Applicant Tracking System</a></h3> <p>The ATS (Applicant Tracking System) is software typically used by companies to track the progression of applicants for a role. But you may commonly hear terms such as ATS-friendly for a resume. Many companies will scan your resume, and the software will then rip out keywords and try to make sense of your resume. For this reason, sticking to <strong>one column</strong> is one of the most important things you can do when writing your resume. Whether a place uses an ATS depends, though larger companies typically use them.</p> <h3 id="word-or-pdf"><a href="#word-or-pdf">Word or PDF?</a></h3> <p>There’s always a debate about whether you should be submitting your resume as a <code>docx</code> file or as a <code>pdf</code> file. This depends on whether they ask you for a <code>pdf</code> file or a <code>docx</code> file, but if they don’t, use a <code>pdf</code> file. In the past, resume parsers would struggle with <code>pdf</code> files, but times have caught up, and <code>pdf</code> files don’t vary as much from computer to computer.</p> <h3 id="curriculum-vitae-cover-letter-resume-whats-the-difference"><a href="#curriculum-vitae-cover-letter-resume-whats-the-difference">Curriculum Vitae, Cover Letter, Resume, What’s the difference?</a></h3> <p>A Curriculum Vitae (CV) is typically a long-form record of your professional journey, and is often a comprehensive document detailing all your achievements, publications, experiences and so on. They can range from two to ten pages. A resume, on the other hand is a concise document detailing relevant experiences to the job you’re applying for. For this reason, a resume is usually kept to one or two pages. A cover letter is a separate document detailing why you’d be a fit for the role in particular, and is usually composed by expanding on your experiences and relating them to the qualifications for the job. I recommend just throwing your resume, and the job description into ChatGPT, and asking it to draft up a cover letter for you.</p> <h3 id="the-importance-of-one-page-resumes"><a href="#the-importance-of-one-page-resumes">The importance of one-page resumes</a></h3> <p>While you may be tempted to fill your resume with a bunch of random leadership roles from high school to make your resume longer, note that you’re only making it harder for a recruiter to pick up valuable insights about the type of candidate you are. While you’re a student, ensure that your resume is at most one page; anything more and a recruiter may miss additional content. Most students won’t have anything meaningful that stretches beyond one page, and if your resume goes beyond two pages, consider re-evaluating the importance of each dot-point on your record.</p> <h3 id="common-nit-picks"><a href="#common-nit-picks">Common Nit-picks</a></h3> <ul><li>Don’t put in the complete link for something, hyperlink it instead, so you have <a href="https://www.google.com" rel="nofollow noopener noreferrer external" target="_blank">Google</a> instead of <a href="https://www.google.com" rel="nofollow noopener noreferrer external" target="_blank">https://www.google.com</a>.</li> <li>Don’t use skill rankings for your technical skills; there’s no way to quantify your expertise and the upper limit of knowledge for a skill in general.</li> <li>Stick to one page, one column resumes.</li> <li>Don’t add your face in; it takes up space and can lead to unintentional discrimination.</li> <li>Don’t add your personal hobbies or interests.</li></ul> <p>These are short and fast rules that I’d stick to.</p> <h3 id="an-objective"><a href="#an-objective">An Objective?</a></h3> <p>Some resumes have a short blurb describing the candidate and any information about them. I’m on the fence with these. You can include them, and it could be helpful; however, you could also argue that it’s a waste of space, up to you.</p> <h3 id="references"><a href="#references">References</a></h3> <p>If a company wants your references, they’ll ask for them. For this reason, I omit any mention of references, as they take up space without giving new information about you. Remember, a resume is a summarised document of your professional history, and you should work to ensure each point reflects that.</p> <h3 id="should-you-lie-on-a-resume"><a href="#should-you-lie-on-a-resume">Should you lie on a resume?</a></h3> <p>While I heavily discourage lying on a resume, the standard rule is if you can’t justify or talk about a point, then leave it out. Sometimes, an interviewer will go over your resume and ask you about it, so you should be able to talk about everything you’ve written down.</p> <h2 id="standard-order-of-sections"><a href="#standard-order-of-sections">Standard Order of Sections</a></h2> <p>So, let’s talk about how you should order your resume. Your education typically comes first, followed by work experience, volunteering work, projects, and a skills section. You’re free to switch up the order of volunteering work and projects or omit one if you have nothing for that area. Still, I recommend having the section with more significant information higher up.</p> <h3 id="education"><a href="#education">Education</a></h3> <p>There should not be too much ambiguity here. Put your degree on there, with any majors or minors you are undertaking, along with an expected graduation date. If you have any achievements, such as a scholarship, a unit prize or similar, you can briefly note them here. If you’re a first-year and have anything relevant to your high school, it wouldn’t hurt to put it down. Still, I recommend removing it early on, as your high school is irrelevant to the job you’re applying for. If your WAM/GPA is noteworthy, then you can briefly list it, but you won’t be looked down upon if you don’t list it.</p> <h3 id="experience"><a href="#experience">Experience</a></h3> <p>When ordering your experiences, ensure it’s ordered chronologically, that is the most recent role at the top. When you start university, it’s okay to have unrelated work experience listed; however, as you progress and gain new material, you can remove those experiences. The golden rule for mentioning what you did during each experience is to note frameworks, libraries and languages and also signify the impact of the work you did. Google uses the “X by Y by Z” formula, where you “accomplished X as measured by Y, by doing Z”. I highly recommend doing this where possible. Also, prefer using dot points over sentences; they convey meaning faster (assuming you format them correctly). You don’t need to use the X-Y-Z formula for every dot point, but ensuring its presence helps a recruiter understand what work you did.</p> <h3 id="volunteering--leadership"><a href="#volunteering--leadership">Volunteering / Leadership</a></h3> <p>Any volunteering opportunity you’ve participated in, such as being an active committee member of a society, is invaluable on a resume. My advice for this section is similar to the experience section in that you should use the “X by Y by Z” formula and mention anything that you believe would be relevant to the role. Additionally, discussing any responsibilities or experience with leadership is generally regarded well.</p> <h3 id="projects"><a href="#projects">Projects</a></h3> <p>The projects section is a valuable way to demonstrate your competency with technical frameworks if you need to gain relevant professional experience and also demonstrate initiative. When adding projects, link the repository it’s hosted on (ensuring it’s public) and any websites they’re linked to. Once again, use the X-Y-Z formula if you can find any impact, for instance, speeding up a slow process, helping students, or making the action point qualitative. Demonstrating your skills in various ways, including showing you’ve brought the application to production, published it on the internet, and so on, are good ways of solidifying the work you’ve done.</p> <h3 id="skills"><a href="#skills">Skills</a></h3> <p>The skills section is more contested for its value, primarily since collections of words don’t convey much meaning, and you can often expand upon technical skills in the other sections. Nonetheless, I highly discourage stating soft skills such as “communication”, “teamwork”, “team player”, and “hard-working” as they convey nothing, and a recruiter will inevitably test you on that in a behavioural interview.</p> <h3 id="achievements"><a href="#achievements">Achievements</a></h3> <p>If you have a lot of achievements, it may be worth creating a new section, briefly outlining each achievement and what the achievement is for. For instance, if you won a scholarship for academic results, briefly state the scholarship is awarded to students who maintain a particular grade.</p> <h2 id="conclusion"><a href="#conclusion">Conclusion</a></h2> <p>This article was split from the other pieces, as it belongs outside the candidate advice section. Still, it is also significant enough to warrant its own <code>.5</code> <del>Final Mix, 358/2 days</del> section. As mentioned, I’d be happy to vet resumes if you DM me. The following article will discuss the various interview formats and how to best approach different interview assessments. In summary, keep your resume concise, and ensure that every point contributes to your potential as a candidate for the job you’re applying for.</p> <h3 id="more-resume-advice"><a href="#more-resume-advice">More Resume Advice</a></h3> <p>As I previously mentioned, what constitutes a good resume is subjective, and you should consult various sources on what your resume could include. I have listed some resources below. Some of these articles may provide advice that contradicts each other, but that’s inevitable when you scrutinise a resume. Alternatively, you could disregard all of my advice and try your hand at tailoring a resume from scratch!</p> <ul><li><a href="https://www.inc-aus.com/bill-murphy-jr/google-recruiters-say-these-5-resume-tips-including-x-y-z-formula-will-improve-your-odds-of-getting-hired-at-google.html" rel="nofollow noopener noreferrer external" target="_blank">Google Recruiters Say Using the X-Y-Z Formula on Your Resume Will Improve Your Odds of Getting Hired at Google</a></li> <li><a href="https://www.levels.fyi/blog/how-to-write-a-good-resume.html" rel="nofollow noopener noreferrer external" target="_blank">How to write a good resume by levels.fyi</a></li> <li><a href="https://www.techinterviewhandbook.org/resume/" rel="nofollow noopener noreferrer external" target="_blank">Practical guide to writing FAANG-ready software engineer resumes</a></li></ul><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="university" scheme="https://https:///?tags=university" />
    <category term="career" scheme="https://https:///?tags=career" />
    <category term="playbook" scheme="https://https:///?tags=playbook" />
  </entry>
  <entry>
    <title type="html"><![CDATA[The Grad/Intern Playbook: Part 2 - Becoming a better candidate]]></title>
    <link href="https://https:///guide-to-tech-2" />
    <id>https://https:///guide-to-tech-2</id>
    <published>2023-06-24T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="introduction"><a href="#introduction">Introduction</a></h2> <p>This is the second article of four articles in my series. The previous article covers the timeline associated with internships and graduate programs. So, how do you maximise your odds of landing a role? The obvious answer is to be the best candidate possible, but how would you do that?</p> <p>There are broadly four significant areas of development for a candidate, whether it’s contributing to what you can talk about or something you list on a resume. Ordered by relative importance, they are:</p> <ul><li>Experience</li> <li>Volunteering</li> <li>Projects</li> <li>Academics</li></ul> <p>We’ll explore each area, but it’s worth noting that <strong>you don’t need stuff in each area</strong> and that two to three areas suffice. This concept is borrowed (somewhat shamelessly) from Nick Lambourne’s <a href="https://blog.ndl.im/getting-that-grad-or-intern-position/#the-four-axes" rel="nofollow noopener noreferrer external" target="_blank">Getting that Grad/Intern Role article</a>. Still, it really captures the broadest distinct criteria that you can undertake to improve your worth as a candidate. It’s also worth noting that some companies (anecdotally) favour one area over another (e.g. having prior work experience). Still, the specifics elude most people, and I’d focus on maximising your worth as a candidate across the board.</p> <h3 id="my-personal-path"><a href="#my-personal-path">My Personal Path</a></h3> <p>One thing I’d also drive home is that everyone’s path through university is unique and that you can end up at the same place by following different paths. In my case, I tutored VCE mathematics in my first year while working on a few personal projects that I was interested in. In my second year, I joined MAC as an events officer. I worked to develop SETool, a web application for comparing university scores. At the end of my second year, I did summer research in deep learning. In my third year, I participated in UniHACK and was the events director of MAC. I did winter research in game theory before becoming the president of MAC and finally interning at Canva as an MLE. Some people I know have chosen to underload work, focusing on gaining professional experience or doing IBL, then getting into the more prominent companies after IBL.</p> <h2 id="experience"><a href="#experience">Experience</a></h2> <p>Being able to list prior relevant work is a huge plus, but it’s only the end of the world if you have that. Most internships don’t require you to have 20 years of experience, as an internship is meant to introduce you to the workplace in a meaningful manner. That being said, some places are very competitive, and because they have a large pool of highly qualified candidates to select from, they may only filter interns with experience.</p> <h3 id="tutoring-and-research-assistant-roles"><a href="#tutoring-and-research-assistant-roles">Tutoring and Research Assistant Roles</a></h3> <p>While in university, the opportunity to tutor may arise as a TA for a subject you’ve taken before, which usually results from doing well in the unit. TA’ing can be time-consuming, as you may be required to mark assignments. Still, it allows you to hone your teaching skills and discuss how you approach teaching in an interview.</p> <p>As for research assistant roles, Monash offers winter and summer research programs, where you work with a professor on a project that usually contributes to some form of research. If you have an interest in academia, I’d especially encourage applying. Even if you don’t have a research interest, the work you do can vary wildly and can give you an idea of what you’d like to work on in the future. For Monash, you’re allowed up to three preferences and 500 words on why you’d be a good choice for any of your projects, which is a bit stupid, considering the tasks you chose could be different. There is some element of luck to these positions, as many people may apply for one project. Still, the choice inevitably comes down to the most convincing written application if the researcher has yet to plan to interview all candidates.</p> <p>The research projects vary in pay and hours, but they tend to not be full-time work (usually). You’ll communicate with a researcher frequently to give status updates and see how the project’s direction is progressing. There’s no harm in applying, and you shouldn’t feel bad if you don’t get a position, as there are many other opportunities to apply for the research programs. It’s also worth noting that sometimes, researchers may reach out to you since they’re interested in what you’ve written to offer your project, which happened in the case of a friend and me. An academic reference is also handy if you wish to apply for postgraduate programs or need a reference for a job application.</p> <h3 id="ibl"><a href="#ibl">IBL</a></h3> <p>As Monash offers the IBL program to anyone studying IT/CS/SE in Eng, you can receive a 6-month placement with a payment of about $20,000 (below minimum wage, in case you want to run the numbers, but it’s technically a scholarship). From memory, the IBL is undertaken in your third year at university, with the placement beginning in January. For this reason, there may be a clash between a summer internship and the IBL program if you do a three-year course. The IBL program is best explained by attending the IBL seminars. Still, you interview companies who score you based on how much they like you. Finally, you are either given a placement or are removed from the program. These internships can vary wildly, with some of my friends tasked to make slides for a couple of months to actual projects impacting the organisation they’ve been assigned to. I don’t have a strong consensus on this program, primarily because it can get in the way of a summer internship, which may be more worthwhile (especially if you’re interested in the more prominent companies) but is also a safer option for securing an internship, while not having to do the project unit you’d typically do. Whatever you choose should be your risk tolerance and the factors above.</p> <h3 id="other-internships"><a href="#other-internships">Other Internships</a></h3> <p>Some other places may offer part-time work or internships; for instance, NAB offers a 6 to 12-month technology internship where you work 4 to 5 days a week at NAB. A common pathway I’ve seen about a program like this is that you can underload during a chosen year to intern at NAB, which gives you exposure to technology while reaping various benefits such as certifications and connections. At this point, you’ll be more prepared for summer internship applications at more reputable companies. If you’re not in a hurry to finish university and want to focus on the experience section, consider finding opportunities for part-time work, as many smaller companies care less about you being a student.</p> <h2 id="volunteering"><a href="#volunteering">Volunteering</a></h2> <p>As I mentioned in the first article, club and student team involvement is seen as an effective method of gaining connections to break into the industry or gain leadership skills that you can discuss in interviews.</p> <h3 id="clubsocietyteam-involvement"><a href="#clubsocietyteam-involvement">Club/Society/Team Involvement</a></h3> <p>These are some of the IT clubs and student teams at Monash:</p> <ul><li>Monash Association of Coding (MAC): We run technical events on upskilling yourself and getting into the industry, for instance, topics in Machine Learning, building an application, or learning about frameworks.</li> <li>MONSEC: A cybersecurity club that runs workshops on the cybersecurity field, such as penetration testing, reverse engineering, cryptography, OSINT, and so on. They run weekly workshops and participate in CTFs (Capture The Flag)</li> <li>WIRED (FITS): The faculty’s official society, which is concerned with social events, technical events, and various other broadly IT-related activities.</li> <li>Commerce and Computing Association (CCA): A club that blends commerce and computing (with the intersection usually being tech consulting). They run more social/networking-related events.</li> <li>Monash Deep Neuron (MDN): An engineering student team focusing on deep learning and high-powered computing. Student teams are more involved, as you’ll be trained in deep learning or high-power computing and work on a project during your time there.</li> <li>Monash Algorithms and Problem Solving (MAPS): A student team focused on competitive programming, with weekly workshops on various competitive programming topics. I’d recommend this if you are interested in the more competitive companies.</li> <li>Monash Data Science Society (MDSS): A student club that is under the Monash Graduate Association (MGA), which is focused on data science.</li></ul> <p>So where should you go? The student teams generally have more commitment, as you’ll be expected to contribute towards long-running projects in addition to training and workshops, but also help contribute towards projects you may list on your resume. MDN looks for people in ML/DL or high-performance computing (HPC), so if your interests lie there, I’d put in an application when they’re recruiting. The other IT student teams, excluding MAPS, are less known to me and are newer, so you can learn more about them <a href="https://www.monash.edu/it/student-teams" rel="nofollow noopener noreferrer external" target="_blank">here</a>. Suppose you’re interested in competitive programming or problem-solving. In that case, I highly encourage you to join MAPS, which now includes running regular workshops on problem-solving.</p> <p>As for student societies, there needs to be more commitment, as each club endeavours to achieve the purposes enshrined in their respective constitutions. CCA and WIRED lean towards being social clubs; however, they still feature sponsored workshops that are technical on occasion, whereas MONSEC and MAC are focused on technical skills primarily. If you’re interested in cybersecurity, I highly recommend MONSEC, and if you’re interested in helping the community by delivering technical workshops, then look at MAC.</p> <h3 id="networking"><a href="#networking">Networking</a></h3> <p>Quite a few students use referrals to increase their chances of getting a role, but what does a referral do? But, if you’re working at a company and know someone who would be an excellent fit for the role, you can refer them, which gives a signal to the recruiter that is, at the very least, better than applying without a reference. Should your friend get the role, you would receive a bonus for the successful referral.</p> <p>The signal I mentioned can vary from company to company; some companies skip a stage of the process, and sometimes, it guarantees your resume will be seen, or it may have no effect (but they won’t tell you that). Nonetheless, if you have a few companies that you’re really adamant about getting into, you can find potential referees by:</p> <ul><li>Cold calling people on LinkedIn, though I recommend sending an invite that conveys interest and intrigue. This approach also varies on the company, as some referrals are more personal, and they may feel uncomfortable handing out a referral to someone they don’t know.</li> <li>Talking to society members; they tend to have done internships at places you may be interested or may know people who have</li> <li>Hanging out on a Discord server - you tend to find a lot of people lurking around</li></ul> <p>With Canva, I chose to apply without any references. I got the role, so it’s by no means a necessity, but it can help your nerves if you need more clarification on your resume. The referee also gets a bonus if you get in (the amount varies wildly), so it’s worth remembering that employees have an incentive for referring you. The other benefit to networking is that you’re able to discover what the company does or anything noteworthy that you can later use in an interview to impress your interviewers or give them a signal that you’ve done your research on this company.</p> <h2 id="projects"><a href="#projects">Projects</a></h2> <p>In place of prior experience, many students opt for the tried and tested approach of developing projects on the side because it shows that you can take the initiative and is a way of contextualising potential skills you’ve acquired. I often get the question of where you find a project, which is hard to answer. I can think of a couple of sources:</p> <ul><li>Hackathons: See below.</li> <li>Subject Projects: You may work in a team to develop something that can be published and refined after you complete it</li> <li>Personal interest: Finding a problem you want to solve or something you want to do is often the best sort of project you can do</li> <li>Research Assistant work: This is basically an internship, but with the university, and may/may not be open source</li></ul> <h3 id="hackathons"><a href="#hackathons">Hackathons</a></h3> <p>Hackathons are competitions where you and a team build and pitch a product, typically over a short time frame, such as 48 hours.</p> <p>Some of the hackathons that run include:</p> <ul><li>UniHack</li> <li>HackAustralia</li> <li>MedHack</li> <li>Hackiethon</li></ul> <p>You can find a list of hackathons <a href="https://www.hackathonsaustralia.com/past-hackathons" rel="nofollow noopener noreferrer external" target="_blank">at hackathonsaustralia</a>. A lot of the time, the winning prizes of these hackathons are web applications, which can be challenging, if not impossible, to do as a first-year if you need to become more familiar with web development. What’s my advice for hackathons? There’s a lot I’d love to talk about. Still, relegating this to a workshop or another article, as there are many strategies and launch pads that you could employ.</p> <p>The most important thing I’ve gained from hackathons is the experience of working with your teammates. There will be many situations where you may disagree with some implementations or have differing views. That way, you’ll have many stories to discuss in behavioural interviews or mould around to answer behavioural questions. Additionally, being able to talk about specific details such as implementation and what you could have added provides fascinating talking points.</p> <h3 id="personal-projects"><a href="#personal-projects">Personal Projects</a></h3> <p>My main point here is that you should only force yourself to do a personal project if you are interested in what you’re doing. If you do have something in mind you want to build, don’t shy away from it. Some common starting grounds for projects include making your own website if you’re a front-end developer, building a discord bot, a full-stack data science dashboard, or a web application for a problem you’re interested in building. I’d recommend using a large language model such as ChatGPT to learn how to tackle a project, including understanding the relevant technologies, what steps you’d need to take, and making a timeline for development.</p> <p>Another reason I suggest embarking on a personal project is because you learn faster by writing code and grappling with how different libraries work.</p> <ul><li><a href="https://github.com/codecrafters-io/build-your-own-x" rel="nofollow noopener noreferrer external" target="_blank">Build Your Own X</a></li> <li><a href="https://github.com/florinpop17/app-ideas" rel="nofollow noopener noreferrer external" target="_blank">App Ideas</a></li></ul> <p>My quick and fast tips for personal projects would be:</p> <ul><li>Do it on something you’re interested in; that way, it feels more natural, and you’re not forcing yourself to work on it</li> <li>Start simple and build on features incrementally to avoid scope creep</li> <li>Document what you do, and make the repository easy to read</li></ul> <h2 id="leetcode--competitive-programming"><a href="#leetcode--competitive-programming">Leetcode / Competitive Programming</a></h2> <p>A significant aspect of the tech industry is the culture around the technical interview, popularised by Google and adopted by everyone in town. While many Reddit posts exaggerate the number of LeetCode problems solved without a FAANG offer, grinding out competitive programming problems and LeetCode helps mainly with the online assessment (OA). There is a degree to which it will help in the technical interview; however, the technical interview is more of a demonstration of your <a href="https://www.techinterviewhandbook.org/coding-interview-rubrics/" rel="nofollow noopener noreferrer external" target="_blank">communication skills (sometimes called coachability), ability to test code, and problem-solve</a>, not just how quickly you solve the problem.</p> <p>Despite saying that, I still recommend doing either the <a href="https://leetcode.com/discuss/general-discussion/460599/blind-75-leetcode-questions" rel="nofollow noopener noreferrer external" target="_blank">Blind 75</a> as supplementary material to your data structures and algorithms course or alternatively gradually working on the <a href="https://neetcode.io/roadmap" rel="nofollow noopener noreferrer external" target="_blank">NeetCode 150 roadmap</a>. I recommend these problem sets because you will become more familiar with approaching problems in an OA. In addition, you should engage in mock technical interviews where you explain how to solve the problem and implement it.</p> <p>Now, you want to truly go the distance and be competitive when solving these problems. In that case, I recommend diving into the world of competitive programming. A modest introduction to competitive programming would be through your local competitive programming club, which in the case of Monash would be the <a href="https://discord.gg/r825Qmk2D2" rel="nofollow noopener noreferrer external" target="_blank">Monash Algorithms and Problems Solving Club (MAPS)</a>, by attending their workshops and attempting problems posed by them. Try your hand at the weekly Leetcode contests or Codeforces if you feel like destroying your sleep cycle. When learning problem-solving techniques, the goal is to progress with challenging problems and consolidate your understanding when you need a new approach to solving a problem.</p> <h2 id="academics"><a href="#academics">Academics</a></h2> <p>The importance of your grade is widely contested, and it doesn’t matter past the screening stage in exceptional circumstances, as some places use your weighted average mark (WAM) as a cheap filter.</p> <p>I’ve heard of companies that may look through your academic transcript and question your grades. My advice is to do your best, but feel encouraged to apply if your grades are different. If your WAM is notable, and you’ve got a commendation such as the Dean’s honour list, put that down on your resume. Some companies may also select you (at the resume stage) based on a high WAM, but these are, again, a few finance firms rather than the majority.</p> <p><!--[-1--><img src="/assets/guide-to-tech/strong_atar.PNG" alt="A company asking for a strong ATAR, and a distinction WAM" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>I’m still trying to figure out what counts as a strong ATAR, but oh well…</p> <h2 id="conclusion---part-2"><a href="#conclusion---part-2">Conclusion - Part 2</a></h2> <p><!--[-1--><img src="/assets/guide-to-tech/be_greater.jpg" alt="Spider-man PS4, Be Greater" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>Whenever you feel like holding back from an opportunity because you don’t feel you can do it, remember <a href="https://youtu.be/q4GdJVvdxss?t=61" rel="nofollow noopener noreferrer external" target="_blank">some say self-doubt is an invitation to be greater, this is your opportunity to prove it.</a> Originally, I was to add a section on resume writing; however, it deserved its own section and will feature in the next article, Part 2.5 <del>Final Mix</del>, Curating your resume. I want to emphasise that there is no one golden path that sits above the rest, as everyone has different interests, and that you should try everything before settling into something that works for you.</p><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="university" scheme="https://https:///?tags=university" />
    <category term="career" scheme="https://https:///?tags=career" />
    <category term="playbook" scheme="https://https:///?tags=playbook" />
  </entry>
  <entry>
    <title type="html"><![CDATA[The Grad/Intern Playbook: FAQ]]></title>
    <link href="https://https:///guide-to-tech-faq" />
    <id>https://https:///guide-to-tech-faq</id>
    <published>2023-06-24T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><p>I’ve received many questions on my article, so this page will act as an index for the most popular questions, and the answers to them.</p> <h3 id="links-to-each-article"><a href="#links-to-each-article">Links to each article</a></h3> <ul><li><a href="../guide-to-tech-1/">The Grad/Intern Playbook: Part 1 - Australia’s Software Engineering Industry and the Timeline</a></li> <li><a href="../guide-to-tech-2/">The Grad/Intern Playbook: Part 2 - Becoming a better candidate</a></li> <li><a href="../guide-to-tech-2.5/">The Grad/Intern Playbook: Part 2.5 Final Mix - Curating your résumé</a></li> <li><a href="../guide-to-tech-3/">The Grad/Intern Playbook: Part 3 - Acing the Interviews</a></li></ul> <h3 id="what-opportunities-are-available"><a href="#what-opportunities-are-available">What opportunities are available?</a></h3> <p>My society, MAC also maintains a job board <a href="https://monashcoding.notion.site/MAC-x-Tech-Internships-ca8d669bec6249b99f5b41cd68e83027" rel="nofollow noopener noreferrer external" target="_blank">which can be found here</a> and we’re actively working to catalogue internships, who they’re available to, and what working rights you need. Aside from that, <a href="../guide-to-tech-1/#the-targets">this section from the first article</a> also covers a range of companies and job posting sites. <a href="https://github.com/AusJobs/Australia-Tech-Internship" rel="nofollow noopener noreferrer external" target="_blank">AusJobs/Australia-Tech-Internship</a> also has a collection of Australian internships with the date they open.</p> <h3 id="what-if-im-not-penultimate"><a href="#what-if-im-not-penultimate">What if I’m not penultimate?</a></h3> <p>The answer is complex, but there are less opportunities. <a href="../guide-to-tech-1/#first-year">See this section in the first article for a non-comprehensive list</a>. The internship/graduate job board maintained by MAC also lists if an internship accepts pre-penultimate students. You are also free to ponder any less honest ideas, such as pretending you’re a penultimate student when you’re really not.</p> <h3 id="where-can-i-find-information-on-making-a-resume"><a href="#where-can-i-find-information-on-making-a-resume">Where can I find information on making a resume?</a></h3> <p><a href="../guide-to-tech-2.5/">In my 2.5 article</a>, where I list my (opinionated) choice of resume which is <a href="https://www.overleaf.com/latex/templates/jakes-resume/syzfjbzwjncs" rel="nofollow noopener noreferrer external" target="_blank">Jake’s Resume</a>.</p> <h3 id="why-is-your-spelling-of-resume-inconsistent"><a href="#why-is-your-spelling-of-resume-inconsistent">Why is your spelling of resume inconsistent?</a></h3> <p>To piss off the one person who would say “umm ackshually, it’s résumé 🤓“.</p> <h3 id="im-a-penultimate-student-what-do-i-do"><a href="#im-a-penultimate-student-what-do-i-do">I’m a penultimate student, what do I do?</a></h3> <p><a href="../guide-to-tech-1/#third-year---penultimate-year">See my first article.</a></p> <h3 id="how-do-i-rizz-the-recruiters"><a href="#how-do-i-rizz-the-recruiters">How do I rizz the recruiters?</a></h3> <p>What?</p> <h3 id="what-do-you-gain-by-doing-all-of-this"><a href="#what-do-you-gain-by-doing-all-of-this">What do you gain by doing all of this?</a></h3> <p>Nothing, really<del>, other than potential referrals</del>. I’m invested in bringing out the potential in people, and I’ve also found that I often have to repeat myself when giving advice to others, so I may as well collate it here. Another reason is that I’m cursed with all this knowledge, and want to note it down somewhere, so I may as well format it.</p> <h3 id="on-natural-talent-versus-hard-work"><a href="#on-natural-talent-versus-hard-work">On Natural Talent versus Hard work</a></h3> <p>I’m a firm believer of 70-80% of your ability coming through hard work. Some people may learn stuff instantly, or be able to solve problems instantly, but the only person you should seriously compare yourself to is you. Being diligient and resilient is hard, but are amazing traits to have in your life, so even if you feel like nothing is going your way, continue to push on. Don’t just push on as you normally do though, actively challenge yourself, your assumptions about the way you learn if you feel it’s ineffective, and really fight the content placed in front of you.</p><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="university" scheme="https://https:///?tags=university" />
    <category term="career" scheme="https://https:///?tags=career" />
  </entry>
  <entry>
    <title type="html"><![CDATA[The Grad/Intern Playbook: Part 1 - Australia's Software Engineering Industry and the Timeline]]></title>
    <link href="https://https:///guide-to-tech-1" />
    <id>https://https:///guide-to-tech-1</id>
    <published>2023-05-06T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h2 id="introduction"><a href="#introduction">Introduction</a></h2> <p>Welcome to The Grad/Intern Playbook! This is a set of articles I wrote documenting my thoughts on how to make it through the technology industry in Australia as a university student. I’m Sai, the <del>current</del> former president of the <a href="https://www.monashcoding.com/" rel="nofollow noopener noreferrer external" target="_blank">Monash Association of Coding (MAC)</a>, and a future Machine Learning Engineer at <a href="https://www.canva.com/" rel="nofollow noopener noreferrer external" target="_blank">Canva</a>, a <a href="https://www.smartcompany.com.au/startupsmart/news/canva-92-5-million-raise-unicorn-19-5-billion/" rel="nofollow noopener noreferrer external" target="_blank">unicorn web design company</a>. Throughout university, I discovered the many, many details of the technical interview process, and how to best prepare for it. Regarding the technology scene in Australia, students from NSW dominate the industry. In contrast, students from Melbourne/Monash are more scarce, partially because I suspect the culture behind sharing the many secrets of the process is too well hidden. I want to document the specifics of the process.</p> <p><!--[-1--><img src="/assets/guide-to-tech/mac_committee_2023.webp" alt="The MAC committee of 2023" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <div class="framed "><p><!---->The best committee I could have asked for...<!----></p></div><!----> <h3 id="inspirations"><a href="#inspirations">Inspirations</a></h3> <p>There already exist articles on getting a grad/intern role in the tech industry, and some of my inspirations come from the following places:</p> <ul><li><a href="https://blog.ndl.im/getting-that-grad-or-intern-position/" rel="nofollow noopener noreferrer external" target="_blank">Getting That Grad/Intern Role</a> - An article by Nick Lambourne, a Canvanaut who inspired me to join Canva. As an article, this is very thorough.</li> <li><a href="https://rohyl.io/blog/how-to-land-a-software-engineering-graduate-role" rel="nofollow noopener noreferrer external" target="_blank">How to Land a Software Engineering Role</a> and <a href="https://rohyl.io/blog/australia-software-engineering-graduate-scene" rel="nofollow noopener noreferrer external" target="_blank">The Best of Australia’s Software Engineering Graduate Scene</a> by Rohyl, a current engineer at Optiver.</li> <li><a href="https://drive.google.com/file/d/1XNoKWgI9Uav6YYXimIAMQRfniC2gA3Gv/view" rel="nofollow noopener noreferrer external" target="_blank">MAC x Guide</a>, which was written by MAC in 2021 and contains tips for Monash IBL, a variety of stories from past MAC members and more.</li></ul> <h3 id="preface"><a href="#preface">Preface</a></h3> <div class="framed "><p><!---->Before you read further, this will be an extremely opinionated article that won't shy away from making concrete points. So, if you've got an eye for making real big bucks out of university (in Australia), here's my guide to software engineering as a university student in Australia. This will also be split into multiple parts, with the first part being an introduction to some of the more prominent companies in Australia and the timeline for when you apply to these companies.<!----></p></div><!----> <h3 id="what-do-you-want-out-of-tech"><a href="#what-do-you-want-out-of-tech">What do you want out of tech?</a></h3> <p>While a lot of people are interested in the tech industry or technical roles because it pays handsomely out of university, there are quite a few intermediate steps to getting a coveted position that pays over $100,000 fresh out of university and that the number of people who do make this much are a small minority. Sure, it may be possible for someone who does no self-guided work in their spare time to get one of these roles. Still, it’s significantly less likely when countless candidates actively maximise their probability of getting in. There’s a discourse on being passionate about programming versus treating it as a role. Still, it would help if you were interested in programming to get far, at least from the start. The rest of what I’ll outline will seem very dull if you’re not invested in different aspects of computer science. <a href="https://www.youtube.com/watch?v=D1sGvTU-sZU" rel="nofollow noopener noreferrer external" target="_blank">ThePrimeTime reacts to a video called Software Engineering Anxiety by bigboxSWE</a>, which eloquently covers a lot of my thoughts on the field as a whole, especially at 9:40, where Prime acknowledges that you shouldn’t make software engineering your life, but also says that there are many more candidates willing to put everything on the line when it comes to job applications. In the end, it’s all up to you, and if you don’t find any joy in it, then you’ll struggle with the entire process.</p> <h2 id="the-targets"><a href="#the-targets">The targets</a></h2> <p>Before you get ahead of yourself and aim for the Big 4 consulting firms because you’ve heard they’re prestigious, let’s discuss technical roles. Technology companies are driven primarily by their software and usually pay the most. Still, there are also quantitative trading firms that hire software engineers to work, which are classified as finance. Companies whose primary product isn’t tech, such as banks, accounting firms, supermarket chains, and so on, generally pay less but have more lenient technical processes (on average). We’ll be examining software engineer/developer roles, which can also include similar roles like data science/machine learning.</p> <ul><li>Tech and quantitative trading firms have more challenging interviews on average but usually pay more. Quantitative trading companies are on the high end for interview difficulty.</li> <li>Non-tech companies who hire developers may have interviews unrelated to what you have studied, e.g. psychometric testing, case studies, etc</li></ul> <p>Technical companies usually have processes for training their engineers and better guidance from mentors who may have decades of experience with different companies. That’s not to say that non-technical companies can’t compare; banks typically pay for certifications or anything to upskill yourself. However, when focusing on technology, you are in an excellent position to learn a lot.</p> <p>More information on the interview processes will be covered in article three.</p> <h3 id="big-tech"><a href="#big-tech">Big Tech</a></h3> <p>Unfortunately, Australia doesn’t have as many options when it comes to big tech companies that have an office here. Nonetheless, there are a few companies that have an office in Sydney or are expanding out with satellite offices in other states. These companies are considered tech because their primary function is selling tech-based products. At the end of each company is <strong>I</strong> for an internship and <strong>G</strong> for graduate roles, with <strong>?</strong> indicating uncertainty.</p> <p>A common occurrence I’ve seen with many students and posts on Reddit is the consensus of an Australian FAANG, which consists of the four companies listed below. I am less invested in ranking companies; however, they have excellent engineers, pay well, and pamper their employees.</p> <ul><li>Atlassian: A software company that develops collaboration and productivity software, including Jira and Confluence. <strong>(I,G, ⭐)</strong></li> <li>Canva: An online graphic design platform that allows users to create various designs, from social media posts to business cards. I interned here as an MLE! <strong>(I,G,⭐)</strong></li> <li>Google: While not an Australian company, Google has a significant presence in Australia and employs many software developers. <strong>(I,G?,⭐)</strong></li> <li>Amazon: Consists of Amazon and AWS, a subsidiary that hires software engineers. <strong>(I,G,⭐)</strong></li></ul> <p>The listed companies are reputable, and most are rumoured to pay well.</p> <ul><li>Airwallex: A fintech company providing cross-border payment solutions for businesses. <strong>(I,G)</strong></li> <li>Rokt: A marketing tech company specialising in personalised offers at the point of transaction to improve e-commerce customer engagement and conversion rates. <strong>(G,⭐)</strong></li> <li>Afterpay: A payment platform that allows users to buy now and pay later, with no interest or fees. <strong>(?,⭐)</strong></li> <li>Bukalapak: An Indonesian e-commerce company that operates an online marketplace connecting buyers and sellers of various products, from electronics to fashion to home goods. <strong>(G)</strong></li> <li>SEEK: A job search website that allows users to search for jobs in various industries and locations. <strong>(G)</strong></li> <li>WiseTech Global: A logistics software company that provides solutions for the logistics industry. <strong>(I, G,⭐)</strong></li> <li>REA Group: A digital advertising company that operates property websites such as realestate.com.au and realcommercial.com.au. <strong>(I*, G)</strong></li> <li>IBM: A technology company that offers a range of solutions in areas such as artificial intelligence, cloud computing, blockchain, and data analytics. <strong>(G)</strong></li> <li>Snap Inc.: A camera and social media company that operates the popular Snapchat app, as well as other products like Spectacles (smart glasses) and Bitmoji (personalised avatar app). <strong>(I,G,⭐)</strong></li> <li>TikTok: A social media platform that allows users to create and share short-form videos set to music or audio snippets. The app has become increasingly popular recently, particularly among younger generations. It has spawned many viral trends and challenges. <strong>(I, G,⭐)</strong></li> <li>Adobe: A software company that writes software aimed at designers, such as Photoshop, InDesign, or Illustrator. <strong>(I, G, ⭐)</strong></li></ul> <p>This list is incomplete as well and is a curation of some I have taken note of. There may also be mistakes, in which case, feel free to get in touch with me! As for the pay, you’ll have to find that yourself, as it will vary yearly and from company to company. But some top companies here pay upwards of 100K and are marked by ⭐, which is very good money. And yes, I used ChatGPT to generate those descriptions.</p> <h3 id="quantitative-trading-firms"><a href="#quantitative-trading-firms">Quantitative trading firms</a></h3> <p>A list of firms that I’m aware of includes Optiver <strong>(I, G,⭐)</strong>, IMC <strong>(I, G,⭐)</strong>, <del>Akuna Capital <strong>(I, G,⭐)</strong>,</del> SIG <strong>(I, G,⭐)</strong>, Jump Trading <strong>(I?,⭐)</strong>, VivCourt <strong>(G,⭐)</strong>, Citadel Securities <strong>(I, G,⭐)</strong>, and Tibra Capital <strong>(I,⭐)</strong>. Jane Street is based in Hong Kong but also takes students from Australian universities. All of these firms pay over $100,000 for a graduate developer role.</p> <p>The consensus with these firms is that you’re more confident with your coding skills, perhaps after a stint in competitive programming. Some, but not all, of these firms also prefer people with Java/C++ experience, so for more flexibility, consider looking into learning one of these languages. Often, some of the companies listed may ask for your WAM or ATAR. From my own experience, these get asked for at the application stage. I’ve seen events where having a high WAM/ATAR is a requirement, but I’ve also heard of students with one or neither of them who’ve got through, so your mileage may vary.</p> <p>These firms also place a heavy emphasis on not requiring a background in finance. However, it helps to have a basic idea of financial instruments, which many places have videos detailing. Suppose you intend to make as much money out of university. In that case, you should highly consider these companies, as Jane Street touts a first-year graduate total compensation of $700,000. However, the amount of people from Monash who intern/work at Jane Street is approximately in the single digits…</p> <h3 id="other-places"><a href="#other-places">Other places</a></h3> <p>Then, there are more companies below that may be worth considering. This list will likely be continually updated.</p> <ul><li>Quantium: A data analytics and AI company serving finance, retail, and healthcare industries. Offers advanced analytics for data-driven decisions. <strong>(I?,G)</strong></li> <li>Carsales.com.au: A digital advertising company that operates automotive classifieds websites such as carsales.com.au and bikesales.com.au. <strong>(G)</strong></li> <li>Telstra: A telecommunications and media company that provides various services, including mobile and internet services, television, and streaming. <strong>(I,G)</strong></li> <li>Macquarie: An Australian investment bank that offers a range of financial services, including asset management, advisory, and banking. Their technology division works on developing innovative solutions to support the bank’s operations and services.</li> <li>Big 4 banks: Westpac, CBA, ANZ and NAB. The experience varies wildly from team to team.</li> <li>CSIRO: Australia’s research agency. They do a lot of work on various topics and offer internships in computing, data science and similar fields.</li> <li>Investment Banks, such as Goldman Sachs, Credit Suisse, Morgan Stanley, etc. These companies hire engineers.</li></ul> <p>The big 4 consulting firms (KPMG, EY, Deloitte, PwC) are also options to consider if you have a few other options. There are many things people say about them: high churn rate, low pay in exchange for a lot of training, not the best if you’re interested in tech, and so on. Standard advice regarding these firms is that they’re a good option during the Monash IBL program as a stepping stone to more prominent places.</p> <ul><li>It’s often common to renege (go back on) on a company if you’ve received a better offer. While I don’t endorse reneging constantly, as you may be blacklisted for doing so, it’s essential to not feel locked down by a company whose offer you accepted early on; this is your career, after all.</li></ul> <h3 id="job-sites"><a href="#job-sites">Job sites</a></h3> <p>Many companies will post their intern/graduate applications on job boards. Some of the most popular sources for finding these include:</p> <ul><li><a href="https://forums.whirlpool.net.au/forum/136" rel="nofollow noopener noreferrer external" target="_blank">The Whirlpool graduate forums</a></li> <li>LinkedIn, especially using <a href="https://www.linkedin.com/help/linkedin/answer/a524335/using-boolean-search-on-linkedin?lang=en" rel="nofollow noopener noreferrer external" target="_blank">Boolean Search</a></li> <li><a href="https://gradaustralia.com.au/" rel="nofollow noopener noreferrer external" target="_blank">GradAustralia</a></li> <li><a href="https://au.gradconnection.com/" rel="nofollow noopener noreferrer external" target="_blank">GradConnection</a></li> <li><a href="https://github.com/AusJobs/Australia-Tech-Internship" rel="nofollow noopener noreferrer external" target="_blank">AusJobs/Australia-Tech-Internship</a></li></ul> <p>I’d recommend noting companies and what they do so that you can apply in future years. In Australia, most companies take on penultimate students for internships, though there are some companies that take on pre-penultimate students.</p> <h3 id="paid-and-unpaid-internships"><a href="#paid-and-unpaid-internships">Paid and Unpaid Internships</a></h3> <p>In Australia, unpaid internships are considered <a href="https://www.fairwork.gov.au/tools-and-resources/fact-sheets/unpaid-work/unpaid-work-unpaid-work" rel="nofollow noopener noreferrer external" target="_blank">unlawful if the intern is considered to be doing “productive” work</a>. If you’re undertaking work experience that is considered vocational, i.e contributes to your education, the internship is considered lawful. For this reason, teachers and nurses embark on unpaid internships. So, internships that you seek out should be paid, and some of the previously mentioned companies pay their interns a very good amount. Some services require you to pay for internship experience; these are illegal and predatory.</p> <div class="framed "><p><p>So typically internships offered as part of some university capstone unit aren’t illegal (The IBL program at Monash for instance), and if they do offer any payment, it’s typically through a tax-free scholarship.</p><!----></p></div><!----> <h2 id="the-timeline"><a href="#the-timeline">The timeline</a></h2> <p>Students typically do three or four-year degrees, whether it’s a standard degree, a double degree, or an honours degree. The penultimate year is before your final year when you apply for internships. If unsuccessful, you can always apply for graduate roles in your last year. That’s not including changes to yourprogression, as many students typically switch degrees, pick up a second degree, or underload.</p> <h3 id="does-the-university-matter"><a href="#does-the-university-matter">Does the university matter?</a></h3> <p>Yes and no. Some places have tiers for universities for hiring, which are commonly known as target schools. However, this seems less common in Australia when looking at tech companies. Some quantitative trading companies may have a preference for universities within the group of 8:</p> <ul><li>University of Melbourne (UniMelb)</li> <li>Australian National University (ANU)</li> <li>University of Sydney (USYD)</li> <li>University of New South Wales (UNSW)</li> <li>University of Queensland (UQ)</li> <li>Monash University (Monash)</li> <li>University of Western Australia (UWA)</li> <li>University of Adelaide (UA)</li></ul> <p>But as to whether it truly matters? It may matter, but there are other considerations for many companies. I’ve seen people work at previously mentioned big tech companies who did not come from the above universities, so it is possible to break into the field.</p> <h3 id="degree-differences"><a href="#degree-differences">Degree differences</a></h3> <p>It’s worth noting that your degree doesn’t matter to a recruiter so long as it’s STEM-related. Hell, some roles don’t even need a STEM degree. You could do computer science and engineering and major in mechatronics/software engineering, IT in software development, science majoring in computational science, etc. It only makes a little difference, except for a few helpful core units. With that being said, some courses are much more useful than others. An example would be doing applied data science at Monash, compared to data science in computer science, also at Monash. Some other examples I can think of are:</p> <ul><li><p>The Monash computer science (CS) and software engineering (SE) degrees have a compulsory data structures and algorithms unit, whereas IT does not</p></li> <li><p>The applied data science (ADS) degree goes into depth regarding machine learning, whereas the data science specialisation leaves room for improvement</p></li> <li><p>The Monash SE, IT, and CS degrees all have the IBL program*, whereas science degrees do not</p></li> <li><p>The SE degree has a compulsory honours year, whereas CS has an optional honours year, and IT has no such honours year</p></li> <li><p>A double degree in science/computer science majoring in mathematics will have more space for math as opposed to computer science on its own</p></li></ul> <p>There are many intricacies to what your degree is, but the result isn’t too significant as long you put the effort in your spare time. This guide will follow a four-year course, but you can still follow the advice as usual anyway, as the timeline would just be a year shorter.</p> <h3 id="getting-more-chancesuniversity-progression"><a href="#getting-more-chancesuniversity-progression">Getting more chances/University progression</a></h3> <p>Some students utilise more extended degrees to get more chances for internships. A typical example would be doing a double degree, where you have two penultimate years, by first considering an alternative exit where you drop a degree or finish both degrees. Underloading is also a viable option, as there’s no rush to complete your degree. Some companies will auto-reject you based on your prospective graduation date, so you could change this to account for dropping a degree/honours year.</p> <p>Three years is short for someone with no prior coding ability to become competent enough. However, it’s possible, assuming you do a bunch of development in your spare time. I’ve heard advice from others regarding underloading/overloading, and the consensus is that it’s okay to underload, as 4 units while managing other commitments or working towards a career can be very daunting. There’s genuinely no rush to finish early, as you’ll be less prepared for whatever comes after.</p> <p>To summarise, you may extend the amount of time you have till you find an internship by:</p> <ul><li>Underloading so that you finish your degree later</li> <li>Doing a double degree or an honours year on top of your degree</li> <li>Pretend that you graduate earlier using an honours year or double degree and say you intend to drop it.</li> <li>I don’t endorse this, but you can also fake a penultimate year to stack multiple internships. What you get out of this is beyond me, besides getting a feel for where you want to go.</li></ul> <h3 id="blacklisting"><a href="#blacklisting">Blacklisting</a></h3> <p>I have seen people mention being “blacklisted” by a company. In practice, the blacklist is more of a cool-down period, where you cannot apply for another role at that company for some time, typically 6 to 12 months. To be blacklisted means you’ve done something that is likely illegal, not just because you applied to the company and got rejected. From what I have gathered, IMC, Jane Street, Google, and Canva implement cool-down periods of varying lengths, and this is usually done to lower the burden of applications.</p> <h3 id="first-year"><a href="#first-year">First year</a></h3> <p>There are a few places that offer pre-penultimate internships, but these are not expected. This would be the Google STEP program and Optivers internships. The Google STEP program is conflicting on who can enter, as there were years when it was entirely women, though I have heard opportunities have opened up to everyone after that year.</p> <p>Some other programs that may be of note include:</p> <ul><li>IMC launchpad: A short experience that could get you fast-tracked to the final round of an IMC internship in the following year</li> <li>Optiver FutureFocus: A similar thing to IMC Launchpad but Optiver-themed</li> <li>SIG Discovery Day: Same as above, but SIG</li> <li><del>Akuna’s winter internship</del></li> <li>Big 4 insight programs</li></ul> <p>Even so, you should be okay with not finding an internship in your first year. It’s exceptional if you do! It’s also common to not know that these internships exist, as they sometimes open at the start of the year when you may have yet to begin classes. Smaller companies may also be happy to take you on as an intern or as a part-time developer if you’re enthusiastic.</p> <p>I suggest drilling down on your programming classes, as they will evolve in difficulty. Another aspect should be learning about different fields in programming. The introductory courses teach Python or C, which are good languages, but don’t scratch the surface if you’re interested in web development or another field. Some suggestions include:</p> <ul><li>Learn another language (Java, C++, Rust, JavaScript, Haskell, OCaml)</li> <li>Learn a framework for the above languages</li> <li>Attempt a personal project</li> <li>Get involved with club events</li> <li>Talk with people!</li> <li>Do a research project (see second year)</li></ul> <p>If your goal is to aim for the big leagues, you can maximise your odds by doing this sort of stuff early on. The things you’ll need to focus on are covered in the second article. An understated part of the internship/graduate grind is talking to other people, as you’ll get a better idea of what you want to do, what you want to aim for, and what you should be doing.</p> <p>My recommendation is to become familiar with clubs/societies at your university. For Monash, this would be:</p> <ul><li>Monash Association of Coding (MAC): We run technical events on upskilling yourself and getting into the industry, for instance, topics in Machine Learning, building an application, or learning about frameworks.</li> <li>MonSec: A cybersecurity club that runs workshops on the cybersecurity field, such as penetration testing, reverse engineering, cryptography, OSINT, and so on. They run weekly workshops and participate in CTFs (Capture The Flag)</li> <li>WIRED (FITS): The faculty’s official society, which is concerned with social events, technical events, and various other broadly IT-related activities.</li> <li>Commerce and Computing Association (CCA): A club that blends commerce and computing (with the intersection usually being tech consulting). They run more social/networking-related events.</li> <li>Monash Deep Neuron (MDN): An engineering student team focusing on deep learning and high-powered computing. Student teams are more involved, as you’ll be trained in deep learning or high-power computing and work on a project during your time there.</li> <li>Monash Algorithms and Problem Solving Society (MAPS): A student team focused on competitive programming, with weekly workshops on various competitive programming topics. I’d recommend this if you are interested in the more competitive companies.</li></ul> <p>As for how much involvement you should aim for, that’s a matter of choice. You can join most of the events/workshops these clubs run and talk to the regulars/committee members to learn more. Alternatively, you could become a committee member yourself, which is a positive on a resume.</p> <h3 id="second-year"><a href="#second-year">Second year</a></h3> <p>You will have likely completed a few computer science units at this point; however, whether you will have completed the first algorithms and data structures course depends on your university. Monash and UniMelb only do this in the first semester of Y2, whereas it may be different with UNSW’s trimesters. Assuming you’ve participated in club activities and done some programming in your first year, now it’s time to start drilling down on some of the interview-specific skills and honing your general ability.</p> <p>Two invaluable outlets for students through the university would be tutoring their introductory units or research assistant work. Teaching students how to write code is a valuable experience. It reinforces your ability, often considered a higher form of understanding. A research assistant also exposes you to research topics in computer science/technology, which gives you a topic to talk about in interviews, in addition to getting paid. The winter research program opens around week nine in semester one, and the summer research program opens around a similar week in semester two. At Monash, TA positions have become available to first years if you’re exceptional.</p> <p>Overall, I’d recommend doing the following:</p> <ul><li>Attend any networking nights that societies advertise. Make sure you talk with other students and not just the recruiters!!</li> <li>Start looking into Leetcode and consider the Blind75/Neetcode150 set of problems</li> <li>Continue working on any personal projects you may have</li> <li>Participate in a hackathon with friends</li></ul> <p>So, by the end of the year, you’re comfortable writing code in two languages, have experiences to discuss in interviews, and can nail a coding assessment. I did this through the second year and did Leetcode every day for a month straight in the summer leading up to the third year. I also did a research program in deep learning over the summer to continually hone my skills. You also don’t need to do everything on this list; they are recommendations for immersing yourself and becoming familiar with software engineering and also being able to nail a behavioural interview through your own experiences.</p> <p>As for potential internship outlets, if you’re still considered pre-penultimate, refer to the year one pre-penultimate program. Additionally, CSIRO has internships through Data61, which take “exceptional” second years, regardless of whether you’re penultimate. Remember, there’s no harm in applying, as you’ll get better with each attempt. NAB also offers its technology program throughout the semester if that would be something you’re interested in.</p> <h3 id="third-year---penultimate-year"><a href="#third-year---penultimate-year">Third year /  Penultimate year</a></h3> <p>By the time you’ve reached your penultimate year, you will have had quite an amount of experience from clubs, writing code in your own time, hackathons, research, tutoring, or a pre-penultimate internship. The goal is now to smash your internship interviews so that you’ll be set for the summer. The big tech companies release their internship applications between January and March, and quantitative trading firms follow a similar timeline. Non-technical companies open up later; for instance, the banks open around mid-year. It is worth noting that ML at Canva only opened in September (in 2022, it’s back to normal), so there are always exceptions to the rule of thumb.</p> <p>So, the game plan is to have your resume ready (DM me if you want your resume vetted!), be familiar with technical assessments, have a collection of stories you can format using STAR, and have a lot of willpower. These interviews are tiring, as applying to upwards of 10 companies during the semester and progressing is rather taxing. It’s also worth it that you use it sooner rather than later, as some of these companies receive upwards of 10k applications. It may be a while before your application is processed, by which point the number of spots would have filled up.</p> <p>One less-known secret is reaching out to people from networking nights, LinkedIn, Discord or other social media for potential referrals, which can have various effects. Usually, it guarantees your resume will be seen by a recruiter. I have reached out to people on LinkedIn in the past, asking questions about the company or the interview process, and they are usually happy to answer and even provide a referral. There’s no harm in doing so, assuming your message is phrased appropriately.</p> <p>Some advice I have:</p> <ul><li>Apply early, apply early, apply early! Even if you feel less than 100% before, the earlier you get in, the less likely that roles will be filled.</li> <li>Have no shame in getting your resume vetted. Seriously, hang your dignity up and get feedback continuously; it could make a big difference.</li> <li>Your first time interviewing, or even going through the process, is likely going to suck. It’s just through repeatedly failing that you become comfortable with the process.</li> <li>Apply to companies that you may not be as interested in, just for the reason above. It’s a win-win scenario; you either learn from failure or get an offer.</li> <li>If you have one offer in hand, ask a recruiter to expedite the process of another interview.</li> <li>Log all the feedback you get; it’s a no-brainer, as you should be able to refine your performance based on that.</li> <li>The interview process is different to the job, <a href="https://www.youtube.com/watch?v=ubOhA56G_tk" rel="nofollow noopener noreferrer external" target="_blank">so you shouldn’t feel discouraged if the whole process feels arbitrary and difficult.</a></li></ul> <p>As for each of the interviews, I’ll be covering that in the third article.</p> <h4 id="addendum-a---summer"><a href="#addendum-a---summer">Addendum A - Summer</a></h4> <p>Congrats! You’ve landed a summer internship, but it’s still ongoing. Typically, companies hire interns as a cheap method to scout out graduate talent and give them return offers to get them on board early. However, in recent years, with a rough market, the headcount at various companies in some teams has shrunk or frozen, meaning that you may have to work to impress during your internship. As a result, the intern-to-graduate conversion offers have decreased. Some of my tips during the internship would include:</p> <ul><li>Establishing a good relationship between you and your host/supervisor, which includes regular communication on the project, participating in standups and so on</li> <li>Try to finish your project or get it to a state that you can talk about</li> <li>Don’t work over the required hours; this may seem like a no-brainer, but don’t buy into the corporate grind mindset; IMO, it’s unhealthy</li> <li>Get to know your peers! If they’ve ended up in the same place you have, there will always be something you can learn from them, whether it’s about other companies or just gossip.</li></ul> <h4 id="addendum-b---course-placements"><a href="#addendum-b---course-placements">Addendum B - Course Placements</a></h4> <p>At Monash, there is an industry-based learning (IBL) program that lets you do an internship for around 6 months. You get paid around $19,000 as a scholarship instead of completing a computer science project. These are primarily companies in Melbourne, and the work can vary from making slides to proper development. Where you end up depends on your performance in the interviews and luck.</p> <p>Under normal progression, the <a href="https://www.monash.edu/it/industry-based-learning/key-student-information" rel="nofollow noopener noreferrer external" target="_blank">IBL placement</a> is done at the start of your third (for a regular computer science student), replacing the computer science project. The internship starts in late January, meaning it may conflict with any summer internships if you’re in a 3-year degree.</p> <p>As for whether this is worth it, that once again depends on what you make of the opportunity; while it is below minimum wage, you are gaining invaluable experience that can be hard to come across. On the flip side, if you were confident in your abilities to secure your own internship, then go ahead; however, you’ll have to complete a project-based unit instead, which will most certainly involve teamwork. Anecdotally, I’ve heard of a few of the IBL-partnered companies paying over 100K once you take a graduate role with them.</p> <ul><li>Alternatively, you can do both by using up the leave from either of the internships.</li> <li>One opinion I’ve heard about doing IBL is that technically, you still have to pay 3,000 for enrolling in the unit, so you’re earning less than 19k, and an internship would be better.</li></ul> <h3 id="fourth-year--final-year"><a href="#fourth-year--final-year">Fourth year / Final year</a></h3> <p>If you’ve reached your final year of university and are having an existential crisis because you didn’t do an arbitrary amount of grinding/prep work, your best bet would be graduate programs if you intend to not delay the progression of your course. Graduate programs, on average, take in fewer students than intern programs, so they are inherently more competitive. Graduate programs usually have more rounds than their intern counterparts as well. As of 2023, the tech industry has shrunk partially because of economic conditions, and lending money is becoming expensive. The consequences of this include layoffs, reduced headcount for some teams, and more competition for roles. Australia is not as impacted as the USA. Still, it’s important to consider job prospects and how to make yourself a more competitive applicant.</p> <p>At this stage, your options are mostly the same as in previous years: take any opportunity to apply or partake in opportunities because each experience gives you more feedback or something you can learn for the future. Graduate roles are open even 12-18 months after you graduate, so there’s always the following year/or the next 6 months because some places have mid-year intakes.</p> <h3 id="conclusion---part-1"><a href="#conclusion---part-1">Conclusion - Part 1</a></h3> <p>There is much to note regarding landing a role in the tech industry as a university student. I intend to split this into four parts as follows:</p> <ul><li>Part 1 - The timeline</li> <li>Part 2 - Becoming a better candidate</li> <li>Part 2.5 - Crafting your resume</li> <li>Part 3 - Tackling the interview process</li></ul> <p>To summarise this article, actively work to learn more about the industry and programming, talk to many people, and participate in events throughout the university. But most importantly, push your own limits, challenge your beliefs by trying, and if that isn’t enough, remember <a href="https://youtu.be/zgMYPTa_1G8?t=195" rel="nofollow noopener noreferrer external" target="_blank">Gojo’s words,</a> and <a href="https://youtu.be/Hk_xBxYmIqY?t=68" rel="nofollow noopener noreferrer external" target="_blank">imagine a future version of yourself who’s freely surpassed your limits.</a> If you’re interested in learning more, you can always reach out to me :)</p> <p><!--[-1--><img src="/assets/guide-to-tech/surpass.jpg" alt="A future me (Domain Expansion) can surpass his limit" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <!--[-1--><div class="sprite-wrapper medium"><span class="pokesprite pokemon marshadow-gen7"></span></div><!--]--><!----><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="university" scheme="https://https:///?tags=university" />
    <category term="career" scheme="https://https:///?tags=career" />
    <category term="playbook" scheme="https://https:///?tags=playbook" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Neochomp - Blog 1]]></title>
    <link href="https://https:///neochomp-blog-1" />
    <id>https://https:///neochomp-blog-1</id>
    <published>2023-03-04T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h1 id="origins-and-starting-off"><a href="#origins-and-starting-off">Origins, and starting off</a></h1> <h2 id="background"><a href="#background">Background</a></h2> <p>While watching <a href="https://www.youtube.com/watch?v=1FliVTcX8bQ" rel="nofollow noopener noreferrer external" target="_blank">Ado’s music video for One Piece Film Red: New Genesis</a>, I noticed that the video incorporated pixelated displays.</p> <p><!--[-1--><img src="/assets/neochomp/blog-1/ado.webp" alt="Untitled" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p><!--[-1--><img src="/assets/neochomp/blog-1/newgenesis.webp" alt="Untitled" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>Because I absolutely needed to see the animation on a cute pixel screen, I came across a cute LED display known as the Tidbyt.</p> <p><!--[-1--><img src="/assets/neochomp/blog-1/train_1.jpeg" alt="What a cute display of train times!" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>What a cute display of train times!</p> <p>Unfortunately, the price point was a rather exorbitant USD 199… So, naturally, I asked, how the hell do you replicate this? My first few searches for an LED matrix display led to devices powered by a Raspberry Pi, which have been the victim of scalping, and a shortage of silicon chips, leading to some ridiculous prices.</p> <p><!--[-1--><img src="/assets/neochomp/blog-1/pricey.webp" alt="So much for hobby price computers…" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>So much for hobby price computers…</p> <p>But we’ll return to our substitute. In the meantime, let’s review the Tidbyt.</p> <h3 id="how-does-the-tidbyt-work"><a href="#how-does-the-tidbyt-work">How Does the Tidbyt Work?</a></h3> <p>During our research on the Tidbyt, we discovered how it operates under the hood. The display is connected to a microcontroller, specifically an ESP32. This means that the frames of animations are not actually rendered on the device itself. Instead, we deduced that a server renders the frames of the selected applet and then sends them to the Tidbyt. The Tidbyt team has designed Pixlet, a software used for rendering pixel animations. You can read more about this process below.</p> <p><a href="https://hackaday.io/project/169732-tidbyt-hackable-led-matrix" rel="nofollow noopener noreferrer external" target="_blank">Tidbyt: Hackable LED Matrix</a></p> <p><!--[-1--><img src="/assets/neochomp/blog-1/teardown.webp" alt="A tear down of the Tidbyt." class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>A teardown of the Tidbyt.</p> <p>Pixlet is an application that renders applets written in Starlark, to pixel displays. The output is a GIF/WebP which could then be sent to the Tidbyt. However, there is no restriction on what display you can render it on, aside from it being 32 by 64 pixels. This meant that we could leverage any applets written for Pixlet and use them for our own devices. Neat!</p> <h2 id="gathering-ingredients"><a href="#gathering-ingredients">Gathering ingredients</a></h2> <h3 id="partners-in-stinginess"><a href="#partners-in-stinginess">Partners in stinginess</a></h3> <p>Since this was a hardware project, I enlisted the partnership of Shin, an engineering and design student. Many of the components, such as the LED display were readily found cheap on Alibaba.</p> <h3 id="the-search-for-the-sbc-substitute"><a href="#the-search-for-the-sbc-substitute">The search for the SBC substitute</a></h3> <p>A Raspberry Pi is commonly referred to as a single-board computer (SBC) since it contains all the components required to run a computer operating system. However, we wanted to minimize the costs for this project as a proof point, so we were forced to look for alternatives.</p> <p><!--[-1--><img src="/assets/neochomp/blog-1/rpi.png" alt="There are desktop computers that are cheaper than this…" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>There are desktop computers that are cheaper than this…</p> <p>Note, that at this point in time, we were looking for a raspberry pi, or an alternative with 40 pins, as there was a bonnet that could be used to mount the device to the display. It’s worth noting a few things though:</p> <ul><li>Raspberry Pi is more closed off than you would think, its bootloader is closed off</li> <li>Even if you found another SBC with 40 pins, they will never correspond to the same things the Raspberry Pi boards do, meaning the RGB bonnet was (mostly) worthless</li> <li>Supposing you somehow overcame that obstacle (rewiring?), all the software written for LED displays was written for the Raspberry Pi line, so good luck getting your random clone from Shenzen to work…</li></ul> <p>And so, our goose chase for this phantom SBC which we couldn’t even be sure if we could program once we got it. Our first candidate was the hilariously named Banana Pi M2.</p> <p><!--[-1--><img src="/assets/neochomp/blog-1/banana.webp" alt="'Hell yeah looks like a mostly shameless clone' - Shin" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <div class="framed "><p><!---->“Hell yeah looks like a mostly shameless clone” - Shin<!----></p></div><!----> <p>Now, the Banana had some heating issues, though that was definitely the least of our concerns. At this time, a cheap little SBC called the Radxa Zero came to our attention, for an insanely affordable USD 30. It’s also important to note that this was a quad-core SBC, which was on par with the Raspberry Pi 4, for a quarter of the price, and could go up to 4GB RAM (Starting at 512 Mb). We were dealing with one beast of a board. So, we put in an order for all the parts.</p> <p><!--[-1--><img src="/assets/neochomp/blog-1/total.png" alt="Untitled" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>As far as major costs were concerned, we were well under $100 per potential product. So, we waited a few weeks for our products to come through.</p> <h2 id="terrible-ideas-i"><a href="#terrible-ideas-i">Terrible Ideas I</a></h2> <p>The engineering process always consists of terrible ideas that somehow made it to our brains.</p> <p><!--[-1--><img src="/assets/neochomp/blog-1/experience.png" alt="The hardware experience. None of these things was actual concerns for us." class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <div class="framed "><p><!---->The hardware experience. Most of the project was fine and we didn't have that many hiccups.<!----></p></div><!----> <h2 id="cool-ideas-i"><a href="#cool-ideas-i">Cool Ideas I</a></h2> <p>On the other hand, we also discovered a variety of interesting ideas, many of which were made accessible via Pixlet. For instance, a transport display for the Melbourne public transport system, similar to the existing ones:</p> <p><a href="https://www.reddit.com/r/TIDBYT/comments/u1gtok/not_a_huge_fan_of_the_official_mta_app_so_i_made/" rel="nofollow noopener noreferrer external" target="_blank">Not a huge fan of the official MTA app, so I made my own</a></p> <p>We found a <a href="https://vic.transportsg.me/mockups" rel="nofollow noopener noreferrer external" target="_blank">website</a> that also creates mockups of the PIDs found in Melbourne train stations, which we could consider a baseline for our task.</p> <p><!--[-1--><img src="/assets/neochomp/blog-1/ptv.png" alt="Untitled" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>Another idea we had was having events trigger on google calendar events. This <a href="https://www.youtube.com/watch?v=BIGsW0TYSuU&amp;ab_channel=VEEBProjects" rel="nofollow noopener noreferrer external" target="_blank">project</a> creates coffee automatically at certain times, and it would be very interesting to have the display be programmed in advance.</p> <!--[-1--><div class="sprite-wrapper large"><span class="pokesprite pokemon meloetta"></span></div><!--]--><!----><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="C" scheme="https://https:///?tags=C" />
    <category term="Python" scheme="https://https:///?tags=Python" />
    <category term="SBC" scheme="https://https:///?tags=SBC" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Neochomp]]></title>
    <link href="https://https:///neochomp" />
    <id>https://https:///neochomp</id>
    <published>2023-03-03T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><p>Neochomp is an LED Matrix display powered by a single-board computer (SBC), a microcontroller, and the Pixlet library, for rendering GIFs in a 32x64 grid. This is a project done with the help of my friend <a href="https://seejianshin.com/" rel="nofollow noopener noreferrer external" target="_blank">Shin</a>, an engineering and design student who has made much of this process possible, including the hardware and design process.</p> <p>The source code for the project can be found <a href="https://github.com/saikumarmk/neochomp" rel="nofollow noopener noreferrer external" target="_blank">here</a>, and blogs on the development of this display will be added.</p> <!--[-1--><div class="sprite-wrapper large"><span class="pokesprite pokemon klinklang"></span></div><!--]--><!----><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="C" scheme="https://https:///?tags=C" />
    <category term="Python" scheme="https://https:///?tags=Python" />
    <category term="SBC" scheme="https://https:///?tags=SBC" />
  </entry>
  <entry>
    <title type="html"><![CDATA[HECS and CSP explained]]></title>
    <link href="https://https:///hecs-and-csp" />
    <id>https://https:///hecs-and-csp</id>
    <published>2023-02-19T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><p>Congrats! You’re a fresh university student who likely chose a course on a coin flip, with regrets yet to come. Before you spend years transferring universities because it’s “practically free”, have a look at this <a href="https://www.reddit.com/r/AusFinance/comments/y2eixt/borrowing_power_limited_due_to_hecs/" rel="nofollow noopener noreferrer external" target="_blank">reddit post</a>, or <a href="https://www.reddit.com/r/AusFinance/comments/10fnsdv/crippled_by_hecs_debt_will_take_a_lifetime_to_pay/" rel="nofollow noopener noreferrer external" target="_blank">this one</a>.</p> <h2 id="what-is-hecs"><a href="#what-is-hecs">What is HECS?</a></h2> <p>The HECS-HELP loan is an initiative that pays for your studies. Then, when you start earning over 50,000 (exact figure varying), an amount will be deducted to pay back your loan. No free university :(</p> <p>Many people will tell you that HECS is “interest-free”, and yes, it is true. But, every year, you will accrue an indexation fee to “account for the cost of living”, in other words, inflation. And unfortunately, if you’ve seen the price of eggs, we’re living in inflation-heavy times.</p> <p>In short, if you have around 120k in debt from, say, a law + arts double degree at Monash, with 3.9% indexation, you’ll be paying off around $4680 on top of your principal (the amount you borrowed). It’s worth noting that many humanities units now cost around $1800 per unit, so each year, you will accrue around $14,440 in debt alone. If you think this is unfair, <a href="https://www.theguardian.com/australia-news/2020/jun/19/australian-university-fees-arts-stem-science-maths-nursing-teaching-humanities" rel="nofollow noopener noreferrer external" target="_blank">go take it up with the clowns who thought this was a good idea</a>.</p> <p>So, the moral of the story? University is no longer free, and it can bite you in the ass.</p> <h2 id="whats-csp"><a href="#whats-csp">What’s CSP?</a></h2> <p>A commonwealth-supported position, or CSP for short, is a spot at a university where you pay less per unit, as the government covers the rest. Before 2021, many teams cost around $1000 each, but now, there’s an emphasis on STEM/teaching, which means they’ve become cheaper. Below are the costs of units from 2022 (which have gone up due to inflation).</p> <div class="prose-table-wrap overflow-x-auto mb-4 svelte-521o0"><table class="table svelte-521o0"><thead><tr><th>Contribution Band</th><th>Maximum Contribution Amount (per EFTSL)</th><th>Approximate Cost per Unit</th></tr></thead> <tbody><tr><td>Band 4: Law, accounting, administration, economics, commerce, communications, society and culture</td><td>$14,630</td><td>$1,828.75</td></tr><tr><td>Band 3: Dentistry, medicine, veterinary science</td><td>$11,401</td><td>$1,425.13</td></tr><tr><td>Band 2: Computing, other health, allied health, visual and performing arts, built environment, engineering, science, environmental studies, surveying, professional pathway psychology, professional pathway social work, pathology</td><td>$8,021</td><td>$1,002.63</td></tr><tr><td>Band 1: Agriculture, English, mathematics, statistics, education, clinical psychology, foreign languages, nursing</td><td>$3,985</td><td>$498.13</td></tr></tbody><!----></table></div><!----> <p>In case you think mathematics is the least employable major, traders at Jane Street start with a total compensation upwards of 600K.</p> <p>It’s worth noting that at an undergraduate level if you’re a domestic student, you are nearly always in a CSP-supported spot. However, CSP opportunities are limited at the postgraduate level. Not all institutions offer CSP by default for postgraduate courses, meaning you may have to pay the full domestic fee. This is common for medicine and dentistry students who may have to pay the total cost for their course. It’s worth noting you can defer full-fee course payments to HECS, though you’ll hit the HECS borrowing limit.</p> <h2 id="lifetime-limit-on-study"><a href="#lifetime-limit-on-study">Lifetime limit on study</a></h2> <div class="framed "><p><!---->From 2022 onwards, you are allowed a lifetime of 7 full-time university years. Any more, and you will pay the full domestic fee. In addition, there is a completion rate requirement, which means that if you don't pass at least 50 per cent of the units you have attempted, you will have to pay the total fee rate until you get that completion rate back up.<!----></p></div><!----> <h2 id="moral-of-the-story"><a href="#moral-of-the-story">Moral of the story</a></h2> <p>If you can afford to, take university seriously. If you don’t believe you can take 4 units a semester (eww, trimesters), then under load, and either compensate by doing summer units or extending your degree. You could switch to doing university part-time if required, which will only count for half a full-time year (in short, it’s more complicated than that). Some resources are attached below on this topic:</p> <ul><li><a href="https://www.studyassist.gov.au/sites/default/files/help_publications_2022_csp_booklet.pdf?v=1637039276" rel="nofollow noopener noreferrer external" target="_blank">CSP and HECS-HELP information</a></li> <li><a href="https://www.studyassist.gov.au/help-loans/commonwealth-supported-places-csps" rel="nofollow noopener noreferrer external" target="_blank">StudyAssist</a></li> <li><a href="https://www.monash.edu/students/admin/fees/course/domestic-fee/2021-student-contribution-amount-calculator" rel="nofollow noopener noreferrer external" target="_blank">Monash CSP calculator (the fees are broadly the same across unis)</a></li> <li><a href="https://www.monash.edu/students/admin/fees/course/domestic-fee" rel="nofollow noopener noreferrer external" target="_blank">Monash domestic full fee calculator</a></li></ul> <h2 id="addendum---full-fee-costs-across-universities"><a href="#addendum---full-fee-costs-across-universities">Addendum - Full Fee Costs Across Universities</a></h2> <p>For the more curious, if you’re a full fee paying student, domestic, or international, university tuition fees will vary across the university and degree you’re enrolled in.</p> <div class="sprite-wrapper medium"><span class="pokesprite medicine rare-candy"></span></div><!----><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="university" scheme="https://https:///?tags=university" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Year in review - 2022]]></title>
    <link href="https://https:///2023-update" />
    <id>https://https:///2023-update</id>
    <published>2023-01-29T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.139Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h1 id="the-year-in-review"><a href="#the-year-in-review">The year in review</a></h1> <p>2022 has been an interesting year, and while I started with a few failures, I ended the year on a high note, with several notable goals that I’ve achieved.</p> <h2 id="monash-handbook"><a href="#monash-handbook">Monash Handbook</a></h2> <p>Over the last few months, I’ve worked with some other members of my club to work towards a more informed source of unit information for Monash units, espescially requisite information. One needs only look at <a href="https://handbook.monash.edu/current/units/FIT3047" rel="nofollow noopener noreferrer external" target="_blank">FIT3047</a> to understand the massive issue students face when making an informed decision regarding what they can take. The manually inputted enrollment rules can also be downright impossible to parse, so we have to look elsewhere.</p> <p>In the journey to scrape requisites, I discovered MonPlan, a now discontinued course planner, can verify course plans, which means it can indirectly return course requisites. After some fiddling and a bit of grouping, I managed to get a rough collection of requisites. Then, I used the Monash Handbook API to scrape any other information and collated it. All this code may be found in <a href="https://github.com/monashcoding/TheBetterHandbookAPI" rel="nofollow noopener noreferrer external" target="_blank">this repository</a>.</p> <p>After compiling these requisites, I whipped up a network visualisation of all 5360 or so Monash units. You may find the graph <a href="https://saikumarmk.github.io/monash-handbook-plus/graph" rel="nofollow noopener noreferrer external" target="_blank">here</a>.</p> <h2 id="canva"><a href="#canva">Canva</a></h2> <p>Sometime in September, I applied to Canva’s machine learning engineer internship role, after accepting an offer from CBA. To my surprise, I ended up getting an offer from Canva, where I am now interning over the summer, working with Stable Diffusion. I’ve discovered that Canva is a major powerhouse when it comes to machine learning, and that the web design front you see does not capture how much cutting edge work is being done here. It’s amazing.</p> <h2 id="mac"><a href="#mac">MAC</a></h2> <p>And finally, I’m now president of the Monash Association of Coding. Which means more responsibilities, but as it’s also going to be my last year in university, there’s a lot I want to get done before I’m gone, especially concerning better student engagement for students in the faculty of IT, and an open source program people can get behind.</p> <!--[-1--><div class="sprite-wrapper medium"><span class="pokesprite pokemon lucario"></span></div><!--]--><!----><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="update" scheme="https://https:///?tags=update" />
  </entry>
  <entry>
    <title type="html"><![CDATA[The story of SETool]]></title>
    <link href="https://https:///the-story-of-setool" />
    <id>https://https:///the-story-of-setool</id>
    <published>2022-06-24T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h3 id="introduction"><a href="#introduction">Introduction</a></h3> <p>During the second semester of 2020, I undertook MTH2051 - Introduction to Computational Mathematics. The details of the unit are irrelevant, it is an introductory course on designing algorithms for numerical methods. I mention this unit because it had an unfortunate form of assessment; quizzes with negative marking. The final exam consisted of 20 multiple choice questions, each of which had a negative marking attached to them. Long story short: people were upset with the immutability and unfairness of the exam, attempted to complain, and a lot of bureaucratic action that amounted to nothing.</p> <p>The anger over the inaction raised attention to the SETU, a set of statistics published for each unit and is the collation of student reviews of the unit, namely satisfaction, and forms of assessment, just to name a few. While MTH2051/3051 received scores that reflected the form of assessment and student dissatisfaction, students were outraged at the lack of visibility concerning the SETU data, which were found in obscure locations, accessible, but hard to find. A student had the idea to scrape SETU data and perform some exploratory data analysis, such as grouping units by their school and determining the aggregated scores. At the time, I was experimenting with data visualisation, particularly with the Dash library, which created web dashboards in Python that could be deployed to the internet. Naturally, as most of the software I had written was designed for the general public, I decided it would be incredibly valuable for the Monash community to have easier access to SETU data, and in a more convenient format.</p> <h3 id="designing-a-web-app-with-dash"><a href="#designing-a-web-app-with-dash">Designing a web app with Dash</a></h3> <p>The actual data scraped ranged over nearly all units offered at Monash University, along with SETU completion, the number of people doing the unit, 8-13 learning outcomes, each ranked from 1 to 5, and other less important data points. My first attempt at a dashboard was a simple radar chart, seen below.</p> <p><!--[-1--><img src="/assets/setool/setool_v1.png" alt="SETool v1. It's not very pretty..." class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <p>While a radar chart gives you a generous idea of the performance of a unit, it can’t be easily compared to another unit, and it gives off the feeling of taking up too much space (which, it certainly does!). At this point, I received a recommendation to use a data table with shaded entries, visualising the score, with red being worse, and green being better. So, back to the drawing board, it was. Until I stumbled across the DataTable, an interactive and insanely customisable component that could colour in my cells. The conditional filtering was coded across the colour range of 2 to 5 and works surprisingly fast. All the other details such as unit name, code, invited and responded numbers didn’t require any modifications and I was done with my dashboard. Well, not really, I ended up adding a comparison table where you could drill down units and compare them against each other.</p> <p><!--[-1--><img src="/assets/setool/setool_v2.png" alt="SETool v2's comparison bar. Much better!" class="rounded-lg my-2 max-w-full h-auto" loading="lazy" decoding="async"/><!--]--><!----></p> <h3 id="on-dash"><a href="#on-dash">On Dash</a></h3> <p>Regarding Dash itself, the library is intuitive when being used, they have plenty of examples in their gallery and their documentation is fleshed out. One idea I could not (easily) bring to fruition was turning the site into a static one, mainly because this would require the use of WebAssembly, namely through Pyodide, which to my knowledge does not support Dash in complete capacity, however, there exists an alpha version for which an extremely limited handful of Dash components work here: <a href="https://github.com/ibdafna/webdash" rel="nofollow noopener noreferrer external" target="_blank">https://github.com/ibdafna/webdash</a>. Nonetheless, Dash is a great library and has forced me to learn about deployment solutions, namely Heroku for hosting my site.</p> <h3 id="deployment-to-heroku"><a href="#deployment-to-heroku">Deployment to Heroku</a></h3> <p>Heroku is a platform as a service (PaaS), meaning they’ll host your applications… for a fee, at least if it’s active enough. It’s free for 450 hours a month of usage, but you have to pay for SSL, something I disagree with because TLS encryption shouldn’t be paywalled, as things, like Let’s Encrypt, exists. Anyway, it’s a decent platform for beginners and is a good introduction to deployment. I did struggle with deploying to Heroku, for a range of beginner-related issues, which I’ll write up on, but getting into Heroku sooner than later is a really good idea.</p> <div class="framed "><p><!---->Side note - Heroku sucks ass, though I don't exactly blame them, because their platform ended up being used for nefarious purposes, causing them to remove their free tier. Oh well...<!----></p></div><!----> <h3 id="changes-and-reception"><a href="#changes-and-reception">Changes, and Reception</a></h3> <p>Throughout the two years I’ve been working on SETool, I’ve continuously thought about rewriting the code in R and implementing a dashboard that can be turned into a static site, or using <code>d3.js</code> and rewriting it to be a front-end project. Overall, people find it very intuitive to use, and I’ve recorded over 1000 unique user visits, which is pretty amazing.</p> <!--[-1--><div class="sprite-wrapper medium"><span class="pokesprite pokemon porygon2"></span></div><!--]--><!----><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="Python" scheme="https://https:///?tags=Python" />
    <category term="Dash" scheme="https://https:///?tags=Dash" />
    <category term="Data visualisation" scheme="https://https:///?tags=Data%20visualisation" />
    <category term="blog-post" scheme="https://https:///?tags=blog-post" />
  </entry>
  <entry>
    <title type="html"><![CDATA[Combining WebAssembly and Emulation]]></title>
    <link href="https://https:///emulation-wasm" />
    <id>https://https:///emulation-wasm</id>
    <published>2021-01-24T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.251Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h1 id="webassembly-and-emulation---chip-8"><a href="#webassembly-and-emulation---chip-8">WebAssembly and Emulation - Chip 8</a></h1> <h2 id="introduction"><a href="#introduction">Introduction</a></h2> <p>In recent times, deploying compiled languages such as C, Rust and other languages to web pages has been made possible due to WebAssembly. The technology allows for compiled code on a webpage without much code in JavaScript, which this tutorial intends to go through. In my testing, Emscripten was awkward to set up due to the variety of software required, however, proved to be straightforward when compiling. For the task, I built a basic emulator for Chip-8, which has few opcodes to implement.</p> <div class="framed "><p><h3>Chip-8</h3> Chip-8 is an interpreted system developed in the 1970s and ran on the Chip-8 VM and could run basic video-games, including Pacman (Blinky game), Pong and Space Invaders. It often serves as an excellent introduction to emulation development as there are only 35 opcodes to implement, but still offers a glimpse into how emulators work.<!----></p></div><!----> <h2 id="building-the-emulator"><a href="#building-the-emulator">Building the Emulator</a></h2> <h3 id="a-roadmap-to-implementing-the-emulator"><a href="#a-roadmap-to-implementing-the-emulator">A roadmap to implementing the emulator</a></h3> <p>Due to the simplicity of the Chip-8 system, it’s a menial job to implement all 35 opcodes. That being said, the job is rather tedious and relies on implementing specific opcodes first. After the opcodes have been implemented, SDL is used to create the screen. The second half of this project then utilises WebAssembly to transpile our code to JavaScript. In summary, a list of tasks to develop this emulator include:</p> <ol><li>Develop a system that can read in ROM files, and match opcodes with their instructions.</li> <li>Implement all 35 opcodes for the system. At this point, you may or may not have a graphical interface going, but its ideal to implement each opcode then test graphically later.</li> <li>Implement a graphical interface that reads from the interpreter memory and draws accordingly. At this point, if any instructions are malfunctioning, ensure you implement various checks.</li> <li>add keyboard support. At this point, the emulator is complete on its own.</li></ol> <h3 id="opcode-matching"><a href="#opcode-matching">Opcode Matching</a></h3> <p>A chip-8 ROM consists of readable opcodes and segments with data. Assuming your instructions are appropriately implemented, these data segments shouldn’t be processed by the opcode handler. For implementing opcodes, I used Cowgod’s Chip-8 reference. They come in several formats, with various bits of data attached to them. For the sake of demonstration, <code>t</code> is a placeholder character.</p> <ul><li><code>tnnn</code>, or an address. <code>nnn</code> corresponds to an address and is typically used for function return/jumping. For instance, <code>0nnn</code> tells the interpreter to jump to address <code>nnn</code>.</li> <li><code>tXtt</code>. The letter x talks about the V register X, or more commonly <code>V_X</code>. The interpreter could do several things with a register specified. Consult the reference for this information.</li> <li><code>ttYt</code>. The letter <code>y</code> talks about the V register y (<code>V_Y</code>). This instruction appears when you’re working with two registers.</li> <li><code>tttN</code>. The letter n represents a single hexadecimal character.</li> <li><code>ttKK</code>. Similar to n, but 8 bits over 4 bits.</li></ul> <p>The standard method of detecting which opcode to use involves bitwise operations. In hexadecimal, we have some useful results. Suppose the hexadecimal representation of a number A has two digits. Then:</p> <!----><pre class="shiki monokai" c="true"><div class="language-id">c</div><div class='code-container'><code><div class='line'>int A = 0x23;</div><div class='line'>int B;</div><div class='line'>B = A & 0x0F;</div><div class='line'>printf("%x",B); // -&gt; 0x3</div></code></div></pre><!----> <p>We find a significant result: the bitwise <code>&amp;</code> operation can effectively mask digits so you can use a switch for them. There are two critical takeaways:</p> <ol><li>Any digit that is bitwise ANDed with 0 will result in 0. You may verify this with the binary representations of both numbers.</li> <li>Any digit that is bitwise ANDed with F will result in the digit itself. For instance, <code>E &amp; F</code> in base 2 is:</li></ol> <p><code>0b1110 &amp; 0b1111 = 0b1110</code></p> <p>The last important operation is the SLL and SLR operations. For instance, you may wish to extract the value of the register for some instruction <code>tXtt</code>. <code>tXtt &amp; 0F00 = 0X00</code>. The value is in the wrong position and needs to be shifted 2 bits to the left, so using SLL will give you <code>000X</code>, which can finally be used.</p> <h3 id="using-a-chip-8-reference"><a href="#using-a-chip-8-reference">Using a Chip-8 reference</a></h3> <p>While developing this emulator, I consulted with <a href="http://devernay.free.fr/hacks/chip8/C8TECH10.HTM" rel="nofollow noopener noreferrer external" target="_blank">CowGod’s Chip-8 reference</a> and implemented each opcode according to the pseudocode instructions. Alongside the opcode reference, I was able to determine the interpreter’s display and internal memory with the technical specifications provided.</p> <h3 id="debugging-process"><a href="#debugging-process">Debugging Process</a></h3> <p>When testing the emulator, I utilised a test ROM <a href="https://github.com/corax89/chip8-test-rom" rel="nofollow noopener noreferrer external" target="_blank">https://github.com/corax89/chip8-test-rom</a> to test necessary opcodes. Of course, not every opcode was guaranteed to be functional, so I ensured that the current opcode and next opcode would be printed. This way, I could use a hex viewer (VSCode hex viewer extension or HxD) to decipher the instruction and see the intended behaviour manually. Of course, this all depends on selecting a few core opcodes functional such as screen drawing and function calls. One example of having to debug faulty execution was finding the program halted early due to an unknown opcode instruction. The first task would be to find the opcode location via a hex viewer, then attempting to decode the neighbouring opcodes to see if I was working with code that wouldn’t skip or jump to a region properly.</p> <h3 id="making-use-of-sdl2"><a href="#making-use-of-sdl2">Making use of SDL2</a></h3> <p>SDL2 is designed for peripheral interaction, and drawing graphics and our emulator will need to update keypress information when a key is pushed up or down, and redraw the screen when necessary. A large chunk of the code is just for modifying the display following a screen update whereas the keyboard interaction logic relies on the <code>SDL_PollEvent</code> function, which checks to see if anything has been pressed.</p> <h3 id="preparing-for-wasm"><a href="#preparing-for-wasm">Preparing for WASM</a></h3> <p>Conveniently, SDL2 has support for WASM and works seamlessly with a simple change for the build command. By providing the argument <code>-s USE_SDL=2</code>, <code>emcc</code> compiles with SDL in mind. However, the code itself requires some modification for web-deployment, as functions are not called forever in a browser, but rather periodically. Below is the code you need to insert in the <code>main</code> function:</p> <!----><pre class="shiki monokai" c="true"><div class="language-id">c</div><div class='code-container'><code><div class='line'>#ifdef __EMSCRIPTEN__</div><div class='line'>    emscripten_set_main_loop(main_loop,0,1);</div><div class='line'>#endif</div></code></div></pre><!----> <p>The function <code>main_loop</code> ideally should detect a keypress then emulate one cycle before pausing for some amount of time. At this point, you should be ready to run the application in a web browser. After compiling <code>HTML</code> and <code>js</code> files, run the following in a terminal, preferably in the folder of compilation:</p> <!----><pre class="shiki monokai"><div class='code-container'><code><div class='line'>python -m HTTP.server 8080</div></code></div></pre><!----> <p>Of course, the last argument can be any port. You may now head to <code>http://localhost:8080</code> to find that the application should load up with the emulator. If it does not, open the web console and check for errors, as they correspond to the same error-codes you programmed into your emulator.</p> <h2 id="conclusion"><a href="#conclusion">Conclusion</a></h2> <h2 id="overall-thoughts"><a href="#overall-thoughts">Overall thoughts</a></h2> <p>While the initial Emscripten process proved to be lengthy and convoluted for beginners, the end-results were impressive, considering any knowledge of JavaScript was not required to get an emulator going. While the language of choice was inconsequential in the compilation to WASM, utilising a language such as Rust would have made testing considerably more manageable in unit tests, which is doable on C; however, unit testing and module management are modern on Rust in comparison.</p> <h3 id="future-considerations"><a href="#future-considerations">Future Considerations</a></h3> <p>Some JS and HTML knowledge is required to implement a drop-down menu for changing ROMs to increase useability. Additionally, having a view of registers and the RAM could also be interesting to implement.</p> <!--[-1--><div class="sprite-wrapper medium"><span class="pokesprite pokemon magneton"></span></div><!--]--><!----><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="webassembly" scheme="https://https:///?tags=webassembly" />
    <category term="emulation" scheme="https://https:///?tags=emulation" />
    <category term="C" scheme="https://https:///?tags=C" />
    <category term="tutorial" scheme="https://https:///?tags=tutorial" />
    <category term="blog-post" scheme="https://https:///?tags=blog-post" />
  </entry>
  <entry>
    <title type="html"><![CDATA[VoltChip]]></title>
    <link href="https://https:///voltchip" />
    <id>https://https:///voltchip</id>
    <published>2021-01-24T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h1 id="a-simple-chip-8-emulator-ported-to-wasm"><a href="#a-simple-chip-8-emulator-ported-to-wasm">A simple Chip-8 emulator ported to WASM</a></h1> <p>VoltChip is a simple demonstration of the potential of deploying to WebAssembly, which allows for binary execution of code via webpages. While emulating Chip-8, an interpreted language with 35 opcodes is not unique, implementing the logic and finding that the code works relatively well with minor adjustments shows that the implementation could be upscaled to a Gameboy. The underlying emulation code was written in C, which may not be helpful for testing, but was simplistic for writing up code. The most fascinating aspect of this experiment was the lack of JavaScript written which would normally be essential to web-based projects normally. I intend to deploy the project to a github page in due course with more flexibility, which does require some JavaScript code written. You may find the project here <a href="https://github.com/Theorvolt/web-voltchip" rel="nofollow noopener noreferrer external" target="_blank">https://github.com/Theorvolt/web-voltchip</a>.</p> <!--[-1--><div class="sprite-wrapper medium"><span class="pokesprite pokemon magnemite"></span></div><!--]--><!----><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="webassembly" scheme="https://https:///?tags=webassembly" />
    <category term="emulation" scheme="https://https:///?tags=emulation" />
    <category term="C" scheme="https://https:///?tags=C" />
    <category term="blog-post" scheme="https://https:///?tags=blog-post" />
  </entry>
  <entry>
    <title type="html"><![CDATA[SETools]]></title>
    <link href="https://https:///setools" />
    <id>https://https:///setools</id>
    <published>2021-01-09T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h1 id="a-way-to-summarize-dull-and-hard-to-visualize-unit-data"><a href="#a-way-to-summarize-dull-and-hard-to-visualize-unit-data">A way to summarize dull and hard to visualize unit data</a></h1> <p>SETools is a data visualization web application that takes in unit data and student satisfaction to create a colorful visualization of how well received a unit is. The libraries involved include Dash, Plotly and Pandas. The use of Dash circumvented the need to use a language such as javascript for a frontend and provided powerful interactive visualizations. The aim of this project was to summarize unit information so that anyone could decide which unit to undertake upon having a glance at the colors of the data. You may find a heroku app instance at <a href="http://setool.herokuapp.com" rel="nofollow noopener noreferrer external" target="_blank">http://setool.herokuapp.com</a> and the source code here <a href="https://github.com/Theorvolt/SETool" rel="nofollow noopener noreferrer external" target="_blank">https://github.com/Theorvolt/SETool</a>.</p> <!--[-1--><div class="sprite-wrapper medium"><span class="pokesprite pokemon porygon"></span></div><!--]--><!----><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="data-science" scheme="https://https:///?tags=data-science" />
    <category term="visualization" scheme="https://https:///?tags=visualization" />
    <category term="python" scheme="https://https:///?tags=python" />
    <category term="summary" scheme="https://https:///?tags=summary" />
  </entry>
  <entry>
    <title type="html"><![CDATA[uwucode]]></title>
    <link href="https://https:///uwucode" />
    <id>https://https:///uwucode</id>
    <published>2021-01-08T00:00:00.000Z</published>
    <updated>2026-07-05T15:56:49.255Z</updated>
    <content type="html">
      <![CDATA[<!--[0--><!--[-1--><h1 id="an-esoteric-toy-programming-language"><a href="#an-esoteric-toy-programming-language">An esoteric toy programming language</a></h1> <p>uwucode is an interpreted programming languaged coded in Rust and boasts ridiculous keywords that derive from recent pop-culture. While the language itself may be satirical and impractical to use, it conveys simple aspects of language design in a beginner friendly manner, something of interest to a variety of programmers. I will eventually do a write-up on what I consider is the preliminary essence of language design, and my thought process while designing uwucode. You may find the github page here <a href="https://github.com/saikumarmk/uwucode" rel="nofollow noopener noreferrer external" target="_blank">https://github.com/Theorvolt/uwucode</a>.</p> <!--[-1--><div class="sprite-wrapper medium"><span class="pokesprite pokemon jigglypuff"></span></div><!--]--><!----><!----><!--]--><!----><!----><!--]-->]]>
    </content>
    <category term="uwucode" scheme="https://https:///?tags=uwucode" />
    <category term="summary" scheme="https://https:///?tags=summary" />
  </entry>
</feed>