<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Malcolm Low</title>
    <description>The latest articles on DEV Community by Malcolm Low (@malcolmlow).</description>
    <link>https://dev.to/malcolmlow</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3894359%2F50ab9e6e-a918-40f1-b3b5-a7526195ffa6.jpg</url>
      <title>DEV Community: Malcolm Low</title>
      <link>https://dev.to/malcolmlow</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/malcolmlow"/>
    <language>en</language>
    <item>
      <title>Say Goodbye to Finder. Meet Marta.</title>
      <dc:creator>Malcolm Low</dc:creator>
      <pubDate>Sat, 16 May 2026 03:29:43 +0000</pubDate>
      <link>https://dev.to/malcolmlow/say-goodbye-to-finder-meet-marta-4k0c</link>
      <guid>https://dev.to/malcolmlow/say-goodbye-to-finder-meet-marta-4k0c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://malcolmlow.net/2026/03/11/say-goodbye-to-finder-meet-marta/" rel="noopener noreferrer"&gt;malcolmlow.net&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;macOS Finder has served Mac users faithfully since 1984 — but its age is showing. For anyone who regularly moves files between folders, manages projects with complex directory structures, or simply wants a more keyboard-friendly workflow, Finder's single-pane design quickly becomes a bottleneck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Marta&lt;/strong&gt; is a modern, native macOS file manager that addresses every one of these frustrations. Best of all — it's free.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Marta?
&lt;/h2&gt;

&lt;p&gt;Marta is a dual-pane, keyboard-driven file manager built exclusively for macOS. Developed by Yan Zhulanow, it borrows the powerful two-panel paradigm from classic file managers like Total Commander and Midnight Commander — but wraps it in a clean, native macOS interface.&lt;/p&gt;

&lt;p&gt;It is highly customisable, supports themes, and has its own plugin and scripting ecosystem. But even out of the box, the difference is immediately noticeable.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Install Marta
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Option A — Direct Download (Recommended)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Head to the official Marta website and download the latest release:&lt;br&gt;
&lt;a href="https://marta.sh" rel="noopener noreferrer"&gt;marta.sh&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option B — Install via Homebrew&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--cask&lt;/span&gt; marta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, optionally grant Full Disk Access for unrestricted folder navigation:&lt;br&gt;
&lt;strong&gt;System Settings → Privacy &amp;amp; Security → Full Disk Access → toggle Marta on&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Marta Beats Finder
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🪟 Dual-Pane Navigation — The Game Changer
&lt;/h3&gt;

&lt;p&gt;The single biggest advantage: a &lt;strong&gt;side-by-side dual-pane view&lt;/strong&gt;. Your screen is split into two independent file panels, each showing a different folder. You can see your source and destination simultaneously — copy or move files between them without ever losing your place or juggling multiple windows.&lt;/p&gt;

&lt;p&gt;For power users — developers, academics, content creators — this alone is worth the switch.&lt;/p&gt;

&lt;h3&gt;
  
  
  📁 Create New Folders in Seconds
&lt;/h3&gt;

&lt;p&gt;In Finder, creating a new folder means right-clicking through a context menu. In Marta, it's a single keyboard shortcut (&lt;code&gt;⌘ + ⇧ + N&lt;/code&gt;) — a new folder appears inline, ready to be named. Your workflow never breaks stride.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⌨️ Fully Keyboard-Driven
&lt;/h3&gt;

&lt;p&gt;Navigate, open, rename, copy, move, and delete files without ever touching the mouse. Marta's keyboard-first design means experienced users can fly through file operations far faster than any GUI-only workflow allows.&lt;/p&gt;

&lt;h3&gt;
  
  
  🗃️ Tabs &amp;amp; Bookmarks
&lt;/h3&gt;

&lt;p&gt;Keep multiple folder locations open as tabs within each panel. Bookmark your most-used directories and jump to them instantly — particularly powerful for large project hierarchies.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎨 Themeable &amp;amp; Configurable
&lt;/h3&gt;

&lt;p&gt;Marta supports custom themes and a powerful configuration file (&lt;code&gt;conf.marco&lt;/code&gt;). You can remap shortcuts, add plugins, and tailor the entire interface to your exact preferences.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;Marta won't replace Finder for every macOS task — but as a daily driver for navigating, organising, and moving files, it is simply in a different league. The dual-pane view alone transforms how you work with files, and features like instant folder creation and keyboard navigation make it feel like a tool built for people who actually use their computer seriously.&lt;/p&gt;

&lt;p&gt;If you've ever felt frustrated waiting on Finder's slow animations, losing track of copy destinations, or clicking through five menus just to create a folder — &lt;strong&gt;give Marta five minutes. You won't go back.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://marta.sh" rel="noopener noreferrer"&gt;marta.sh →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>macos</category>
      <category>productivity</category>
      <category>tools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Cost of Garbage in Quantum Computing: Why You Must Clean Up Junk Bits</title>
      <dc:creator>Malcolm Low</dc:creator>
      <pubDate>Sat, 16 May 2026 03:29:12 +0000</pubDate>
      <link>https://dev.to/malcolmlow/the-cost-of-garbage-in-quantum-computing-why-you-must-clean-up-junk-bits-47g5</link>
      <guid>https://dev.to/malcolmlow/the-cost-of-garbage-in-quantum-computing-why-you-must-clean-up-junk-bits-47g5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://malcolmlow.net/2025/12/27/the-cost-of-garbage-why-we-must-clean-junk-bits/" rel="noopener noreferrer"&gt;malcolmlow.net&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In quantum computing, anything that "knows" what a qubit is doing acts as a &lt;strong&gt;Witness&lt;/strong&gt;. Leftover data (&lt;strong&gt;Junk Bits&lt;/strong&gt;) on an ancilla qubit act as witnesses, destroying the interference your algorithm needs to work.&lt;/p&gt;




&lt;h2&gt;
  
  
  1 . The Observer Effect
&lt;/h2&gt;

&lt;p&gt;Consider a simple circuit where a qubit passes through two Hadamard gates. Classically, two inversions cancel. Quantum mechanically, the same is true — &lt;em&gt;only if no information leaks out between them&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case A: Ideal — No Junk&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;q0: |0&amp;gt; --H-----------H-- =&amp;gt; |0&amp;gt;  (100% probability)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two Hadamard gates cancel perfectly. Measurement always yields |0&amp;gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case B: Broken — With Junk&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;q0: |0&amp;gt; --H----*-------H-- =&amp;gt; |0&amp;gt; or |1&amp;gt;  (50/50 noise)
               |
q1: |0&amp;gt; -------X---------- =&amp;gt; |junk&amp;gt;      (records q0's path)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ancilla qubit q1 becomes entangled with q0. It now "knows" which path q0 took — and that knowledge destroys the interference.&lt;/p&gt;




&lt;h2&gt;
  
  
  2 . Mathematical Working
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ideal Case — interference works:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start:    |0&amp;gt;
After H:  (1/sqrt2)(|0&amp;gt; + |1&amp;gt;)
After H:  (1/2)(|0&amp;gt; + |1&amp;gt; + |0&amp;gt; - |1&amp;gt;) = |0&amp;gt;   (cancel!)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The |1&amp;gt; terms cancel — constructive interference on |0&amp;gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Junk Case — interference destroyed:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start:          |0&amp;gt;|0&amp;gt;
After H on q0:  (1/sqrt2)(|0&amp;gt; + |1&amp;gt;)|0&amp;gt;
After CX:       (1/sqrt2)(|00&amp;gt; + |11&amp;gt;)    &amp;lt;- entangled!
After H on q0:  (1/2)(|00&amp;gt; + |10&amp;gt; + |01&amp;gt; - |11&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The terms cannot cancel because q1 differs in each: |00&amp;gt; vs |10&amp;gt; are orthogonal states. Interference is destroyed.&lt;/p&gt;




&lt;h2&gt;
  
  
  3 . The Solution: Uncomputation
&lt;/h2&gt;

&lt;p&gt;To restore interference, follow the &lt;strong&gt;Compute-Copy-Uncompute&lt;/strong&gt; pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;q_in : |x&amp;gt; --[COMPUTE]--+--[UNCOMPUTE]-- |x&amp;gt;    (unchanged)
                        |
q_anc: |0&amp;gt; -------------+--[UNCOMPUTE]-- |0&amp;gt;     (cleaned)
                        |
q_out: |0&amp;gt; -------------+--------------- |f(x)&amp;gt;  (result)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Compute&lt;/strong&gt; — apply your function gates, writing the result onto q_anc&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy&lt;/strong&gt; — CNOT the result from q_anc into q_out&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uncompute&lt;/strong&gt; — run the compute gates in reverse, resetting q_anc to |0&amp;gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With q_anc back to |0&amp;gt;, the witness is gone and interference is fully restored.&lt;/p&gt;




&lt;h2&gt;
  
  
  4 . Qiskit Implementation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;qiskit&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QuantumCircuit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transpile&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;qiskit_aer&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AerSimulator&lt;/span&gt;

&lt;span class="n"&gt;qc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;QuantumCircuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# q0 = input, q1 = ancilla, q2 = output
&lt;/span&gt;
&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# COMPUTE:    entangle q0 -&amp;gt; q1 (creates junk)
&lt;/span&gt;&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# COPY:       copy result q1 -&amp;gt; q2
&lt;/span&gt;&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# UNCOMPUTE:  reverse compute, reset q1 -&amp;gt; |0&amp;gt;
&lt;/span&gt;&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;# Interference fully restored
&lt;/span&gt;
&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;measure_all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;counts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AerSimulator&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;transpile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AerSimulator&lt;/span&gt;&lt;span class="p"&gt;())).&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get_counts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Resulting state: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;counts&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same circuit as a wire diagram (&lt;code&gt;@&lt;/code&gt; = control, &lt;code&gt;X&lt;/code&gt; = target):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;q0: |0&amp;gt; --H--@---------@--H-- M
             |         |
q1: |0&amp;gt; -----X----@----X----- M   (ancilla: |0&amp;gt; -&amp;gt; junk -&amp;gt; |0&amp;gt;)
                  |
q2: |0&amp;gt; ----------X---------- M   (output: holds f(x))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second &lt;code&gt;cx(0,1)&lt;/code&gt; exactly reverses the first, leaving q1 in |0&amp;gt;. With the witness removed, the final &lt;code&gt;h(0)&lt;/code&gt; performs clean interference and q0 deterministically outputs |0&amp;gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5 . Why This Matters in Practice
&lt;/h2&gt;

&lt;p&gt;Uncomputation is not just a theoretical nicety. In real quantum algorithms:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Grover's oracle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Must leave ancilla qubits clean after marking the target, or subsequent diffusion steps decohere&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Arithmetic circuits&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reversible adders/multipliers accumulate garbage at every intermediate step — all must be uncomputed before measurement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fault-tolerant circuits&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Strict qubit budgets; junk bits consume physical qubits that could otherwise be used for error correction&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Compute-Copy-Uncompute pattern is the standard solution across all three contexts.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Quantum Series 2025 · Built with Qiskit 1.x&lt;/em&gt;&lt;/p&gt;

</description>
      <category>quantumcomputing</category>
      <category>qiskit</category>
      <category>tutorial</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Quantum Computing: Grover's Algorithm — Inversion About the Mean</title>
      <dc:creator>Malcolm Low</dc:creator>
      <pubDate>Sat, 16 May 2026 03:18:38 +0000</pubDate>
      <link>https://dev.to/malcolmlow/quantum-computing-grovers-algorithm-inversion-about-the-mean-329o</link>
      <guid>https://dev.to/malcolmlow/quantum-computing-grovers-algorithm-inversion-about-the-mean-329o</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://malcolmlow.net/2026/03/28/quantum-computing-inversion-about-the-mean/" rel="noopener noreferrer"&gt;malcolmlow.net&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Grover's algorithm is a quantum search procedure that locates a marked item in an unsorted list of N items in O(√N) oracle queries — a quadratic speedup over any classical approach. For N = 8 (3 qubits), this means roughly ⌊π/4 × √8⌋ = &lt;strong&gt;2 optimal iterations&lt;/strong&gt; before the probability of measuring the target state peaks.&lt;/p&gt;

&lt;p&gt;This walkthrough tracks the exact amplitude of every basis state through each gate operation for the 3-qubit case, with target state &lt;strong&gt;|101⟩&lt;/strong&gt;. All arithmetic is shown so each step can be verified by hand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure of each iteration (Grover operator G):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Oracle Uf&lt;/strong&gt; — Phase-flips the target state: |x⟩ → −|x⟩ if f(x) = 1, otherwise |x⟩ → |x⟩&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diffusion operator D = H⊗n(2|0⟩⟨0| − I)H⊗n&lt;/strong&gt; — Reflects all amplitudes about their mean, amplifying the marked state at the expense of the others&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key insight:&lt;/strong&gt; The oracle introduces destructive interference at the target, which the diffusion operator converts into constructive interference by inverting amplitudes about their mean. Each iteration rotates the state vector by angle 2θ closer to the target, where sin(θ) = 1/√N.&lt;/p&gt;




&lt;h2&gt;
  
  
  Phase 0: Initialization
&lt;/h2&gt;

&lt;p&gt;Apply H⊗3 to |000⟩ to create a uniform superposition over all 8 basis states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|ψinit⟩ = (1/√8)[ |000⟩ + |001⟩ + |010⟩ + |011⟩
                 + |100⟩ + |101⟩ + |110⟩ + |111⟩ ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every state has amplitude &lt;strong&gt;+1/√8 ≈ 0.3535&lt;/strong&gt; and probability &lt;strong&gt;12.5%&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Hadamard Reference (Standard Signs)
&lt;/h2&gt;

&lt;p&gt;Element (i, j) has sign (−1)^popcount(i AND j). This table is used in every Hadamard step below — each row shows how an input basis state distributes into all 8 output states.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          |000⟩ |001⟩ |010⟩ |011⟩ |100⟩ |101⟩ |110⟩ |111⟩
          ─────────────────────────────────────────────────
H|000⟩ →    +     +     +     +     +     +     +     +
H|001⟩ →    +     −     +     −     +     −     +     −
H|010⟩ →    +     +     −     −     +     +     −     −
H|011⟩ →    +     −     −     +     +     −     −     +
H|100⟩ →    +     +     +     +     −     −     −     −
H|101⟩ →    +     −     +     −     −     +     −     +
H|110⟩ →    +     +     −     −     −     −     +     +
H|111⟩ →    +     −     −     +     −     +     +     −
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Round 1: Oracle → Diffusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — Oracle Uf&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The oracle recognises |101⟩ as the marked state and flips its amplitude from +1/√8 to −1/√8. All other amplitudes remain unchanged. The superposition is preserved — no measurement is made.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4.1 — First H (mapping to Hadamard basis)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each input state contributes ±1/8 to each output column via the sign table. The oracle-marked |101⟩ row is fully sign-inverted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  |000⟩  |001⟩  |010⟩  |011⟩  |100⟩  |101⟩  |110⟩  |111⟩
                  ──────────────────────────────────────────────────────────
+H|000⟩  (+1/√8)  +1/8   +1/8   +1/8   +1/8   +1/8   +1/8   +1/8   +1/8
+H|001⟩  (+1/√8)  +1/8   -1/8   +1/8   -1/8   +1/8   -1/8   +1/8   -1/8
+H|010⟩  (+1/√8)  +1/8   +1/8   -1/8   -1/8   +1/8   +1/8   -1/8   -1/8
+H|011⟩  (+1/√8)  +1/8   -1/8   -1/8   +1/8   +1/8   -1/8   -1/8   +1/8
+H|100⟩  (+1/√8)  +1/8   +1/8   +1/8   +1/8   -1/8   -1/8   -1/8   -1/8
-H|101⟩  (-1/√8)  -1/8   +1/8   -1/8   +1/8   +1/8   -1/8   +1/8   -1/8  ← oracle row
+H|110⟩  (+1/√8)  +1/8   +1/8   -1/8   -1/8   -1/8   -1/8   +1/8   +1/8
+H|111⟩  (+1/√8)  +1/8   -1/8   -1/8   +1/8   -1/8   +1/8   +1/8   -1/8
          ───────────────────────────────────────────────────────────────────
Net 4.1           +6/8   +2/8   -2/8   +2/8   +2/8   -2/8   +2/8   -2/8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4.2 — Phase Flip (2|0⟩⟨0|−I)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keep |000⟩ unchanged, negate all other states. This is the heart of inversion-about-the-mean.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         |000⟩  |001⟩  |010⟩  |011⟩  |100⟩  |101⟩  |110⟩  |111⟩
Post-Z:  +6/8   -2/8   +2/8   -2/8   -2/8   +2/8   -2/8   +2/8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4.3 — Second H (back to computational basis)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  |000⟩  |001⟩  |010⟩  |011⟩  |100⟩  |101⟩  |110⟩  |111⟩
Net R1 (exact):  +4/8√8 +4/8√8 +4/8√8 +4/8√8 +4/8√8 +20/8√8 +4/8√8 +4/8√8
Net R1 (decimal):  0.177  0.177  0.177  0.177  0.177   0.884  0.177  0.177
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After Round 1, |101⟩ has been amplified from 0.354 to &lt;strong&gt;0.884&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Round 2: Oracle → Diffusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 5 — Oracle Uf&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The oracle flips |101⟩ from +20/8√8 to −20/8√8. The 7 non-target states remain at +4/8√8. This large asymmetry drives even stronger constructive interference in the diffusion step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6.1 — First H&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                      |000⟩   |001⟩   |010⟩   |011⟩   |100⟩   |101⟩   |110⟩   |111⟩
                      ──────────────────────────────────────────────────────────────────
+H|000⟩  (+4/8√8)    +4/64   +4/64   +4/64   +4/64   +4/64   +4/64   +4/64   +4/64
+H|001⟩  (+4/8√8)    +4/64   -4/64   +4/64   -4/64   +4/64   -4/64   +4/64   -4/64
+H|010⟩  (+4/8√8)    +4/64   +4/64   -4/64   -4/64   +4/64   +4/64   -4/64   -4/64
+H|011⟩  (+4/8√8)    +4/64   -4/64   -4/64   +4/64   +4/64   -4/64   -4/64   +4/64
+H|100⟩  (+4/8√8)    +4/64   +4/64   +4/64   +4/64   -4/64   -4/64   -4/64   -4/64
-H|101⟩  (-20/8√8)  -20/64  +20/64  -20/64  +20/64  +20/64  -20/64  +20/64  -20/64  ← oracle row
+H|110⟩  (+4/8√8)    +4/64   +4/64   -4/64   -4/64   -4/64   -4/64   +4/64   +4/64
+H|111⟩  (+4/8√8)    +4/64   -4/64   -4/64   +4/64   -4/64   +4/64   +4/64   -4/64
          ──────────────────────────────────────────────────────────────────────────────
Net 6.1              +8/64  +24/64  -24/64  +24/64  +24/64  -24/64  +24/64  -24/64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 6.2 — Phase Flip&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         |000⟩   |001⟩   |010⟩   |011⟩   |100⟩   |101⟩   |110⟩   |111⟩
Post-Z:  +8/64  -24/64  +24/64  -24/64  -24/64  +24/64  -24/64  +24/64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 6.3 — Second H&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                   |000⟩    |001⟩    |010⟩    |011⟩    |100⟩    |101⟩    |110⟩    |111⟩
Net R2 (exact):  -16/64√8 -16/64√8 -16/64√8 -16/64√8 -16/64√8 +176/64√8 -16/64√8 -16/64√8
Net R2 (decimal):  -0.088   -0.088   -0.088   -0.088   -0.088    +0.972   -0.088   -0.088
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Success Probability after Round 2: P(|101⟩) = |0.972|² ≈ 94.5%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Round 2 is the optimal stopping point&lt;/strong&gt; for 3-qubit Grover search — ⌊π/4 × √8⌋ = 2 iterations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Round 3: The Overcooking Effect
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 7 — Oracle Uf&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With P(|101⟩) at 94.5%, one more iteration is one too many. The oracle flips |101⟩ from +176/64√8 to −176/64√8. The state vector has been rotated 2θ past its peak — a third diffusion step pushes it further away from the target, not closer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps 8.1–8.3 — Diffusion&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                   |000⟩    |001⟩    |010⟩    |011⟩    |100⟩    |101⟩    |110⟩    |111⟩
Net R3 (exact):  -448/512√8 (×7 non-target states)    +832/512√8 (target)
Net R3 (decimal):  -0.309   -0.309   -0.309   -0.309   -0.309    +0.575   -0.309   -0.309
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;P(|101⟩) = |0.575|² ≈ 33.0%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Summary: Amplitude Evolution Across Rounds
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Round   Target |101⟩   Non-target states   P(|101⟩)
──────────────────────────────────────────────────────
Init       +0.354          +0.354            12.5%
R1         +0.884          +0.177            78.1%
R2         +0.972          -0.088            94.5%  ← optimal stop
R3         +0.575          -0.309            33.0%  ← overcooked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The state vector has rotated past the optimal angle. P(|101⟩) drops from 94.5% to &lt;strong&gt;33.0%&lt;/strong&gt; — a significant fall, but |101⟩ still has more than double the probability of any other state. The algorithm has not lost the answer; it has merely overshot the maximum.&lt;/p&gt;

&lt;p&gt;Importantly, the target amplitude is still positive (+0.575) — the vector has not crossed zero, it has simply overshot past the maximum. The result comes directly from the Born rule: P(|101⟩) = |amplitude|² = |+0.575|² ≈ 0.330.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Quantum Series 2026 · Built with Qiskit 1.x&lt;/em&gt;&lt;/p&gt;

</description>
      <category>quantumcomputing</category>
      <category>mathematics</category>
      <category>qiskit</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Quantum Computing: The Walsh-Hadamard Matrix — Backbone of Grover's Diffusion Operator</title>
      <dc:creator>Malcolm Low</dc:creator>
      <pubDate>Sat, 16 May 2026 03:13:06 +0000</pubDate>
      <link>https://dev.to/malcolmlow/quantum-computing-the-walsh-hadamard-matrix-backbone-of-grovers-diffusion-operator-4g5l</link>
      <guid>https://dev.to/malcolmlow/quantum-computing-the-walsh-hadamard-matrix-backbone-of-grovers-diffusion-operator-4g5l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://malcolmlow.net/2026/04/03/quantum-computing-the-walsh-hadamard-matrix-backbone-of-grovers-diffusion-operator/" rel="noopener noreferrer"&gt;malcolmlow.net&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the &lt;a href="https://malcolmlow.net/2026/03/28/quantum-computing-inversion-about-the-mean/" rel="noopener noreferrer"&gt;Grover's Algorithm — Inversion About the Mean&lt;/a&gt; walkthrough, the diffusion operator applies H⊗³ twice per iteration. Every single step is governed by a sign table called the &lt;strong&gt;Hadamard Reference&lt;/strong&gt;. That table is not a lookup shortcut — it &lt;em&gt;is&lt;/em&gt; the 8×8 Walsh-Hadamard Transform matrix written out in full. This post derives it from scratch: one qubit, then two, then all three, arriving at the complete matrix and the rule behind every sign in it.&lt;/p&gt;




&lt;h2&gt;
  
  
  1 · The Circuit: Three Qubits, Three Hadamard Gates
&lt;/h2&gt;

&lt;p&gt;We initialise all three qubits in the ground state |0⟩ and route each through its own independent Hadamard gate. There are no two-qubit (entangling) gates — the circuit is entirely parallel.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Qubit&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Gate&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;q₀&lt;/td&gt;
&lt;td&gt;|0⟩&lt;/td&gt;
&lt;td&gt;H&lt;/td&gt;
&lt;td&gt;(1/√2)(|0⟩ + |1⟩)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;q₁&lt;/td&gt;
&lt;td&gt;|0⟩&lt;/td&gt;
&lt;td&gt;H&lt;/td&gt;
&lt;td&gt;(1/√2)(|0⟩ + |1⟩)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;q₂&lt;/td&gt;
&lt;td&gt;|0⟩&lt;/td&gt;
&lt;td&gt;H&lt;/td&gt;
&lt;td&gt;(1/√2)(|0⟩ + |1⟩)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All three outputs are identical because all three inputs are identical. The structure emerges when we take their tensor product.&lt;/p&gt;




&lt;h2&gt;
  
  
  2 · Single-Qubit Hadamard Action
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;H|input⟩&lt;/th&gt;
&lt;th&gt;Short notation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;|0⟩&lt;/td&gt;
&lt;td&gt;(1/√2)(|0⟩ + |1⟩)&lt;/td&gt;
&lt;td&gt;|+⟩&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;|1⟩&lt;/td&gt;
&lt;td&gt;(1/√2)(|0⟩ − |1⟩)&lt;/td&gt;
&lt;td&gt;|−⟩&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In matrix form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H = (1/√2) [ +1  +1 ]
            [ +1  -1 ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key property:&lt;/strong&gt; H is its own inverse — H² = I. Every element has magnitude 1/√2, so tensoring three copies multiplies the magnitudes to 1/√8 while the signs follow a precise bitwise pattern.&lt;/p&gt;




&lt;h2&gt;
  
  
  3 · Two-Qubit Tensor Product: q₀ ⊗ q₁
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|+⟩ ⊗ |+⟩
= (1/√2)(|0⟩ + |1⟩) ⊗ (1/√2)(|0⟩ + |1⟩)
= (1/2)( |00⟩ + |01⟩ + |10⟩ + |11⟩ )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All four two-qubit basis states appear with equal amplitude &lt;strong&gt;1/2&lt;/strong&gt;. Measurement probability per state: (1/2)² = &lt;strong&gt;25%&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  4 · Three-Qubit Tensor Product: q₀ ⊗ q₁ ⊗ q₂
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|+⟩ ⊗ |+⟩ ⊗ |+⟩
= (1/√8)( |000⟩ + |001⟩ + |010⟩ + |011⟩
        + |100⟩ + |101⟩ + |110⟩ + |111⟩ )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is &lt;strong&gt;|ψinit⟩&lt;/strong&gt; — the uniform superposition over all 8 basis states that opens Grover's algorithm. Each state carries amplitude &lt;strong&gt;+1/√8 ≈ 0.3535&lt;/strong&gt; and measurement probability &lt;strong&gt;1/8 = 12.5%&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5 · The 8×8 Walsh-Hadamard Sign Matrix
&lt;/h2&gt;

&lt;p&gt;When H⊗³ is applied to an arbitrary basis state |j⟩:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H⊗³ |j⟩ = (1/√8) Σᵢ (−1)^popcount(i AND j) |i⟩
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entry at row i, column j carries sign (−1)^popcount(i AND j) divided by √8.&lt;br&gt;
&lt;code&gt;+&lt;/code&gt; = amplitude +1/√8 ≈ +0.3535 / &lt;code&gt;−&lt;/code&gt; = amplitude −1/√8 ≈ −0.3535&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          |000⟩ |001⟩ |010⟩ |011⟩ |100⟩ |101⟩ |110⟩ |111⟩
          ─────────────────────────────────────────────────
H|000⟩ →    +     +     +     +     +     +     +     +
H|001⟩ →    +     −     +     −     +     −     +     −
H|010⟩ →    +     +     −     −     +     +     −     −
H|011⟩ →    +     −     −     +     +     −     −     +
H|100⟩ →    +     +     +     +     −     −     −     −
H|101⟩ →    +     −     +     −     −     +     −     +
H|110⟩ →    +     +     −     −     −     −     +     +
H|111⟩ →    +     −     −     +     −     +     +     −
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each row shows how an input basis state |j⟩ distributes its amplitude across all 8 output states after H⊗³ is applied.&lt;/p&gt;




&lt;h2&gt;
  
  
  6 · Why the Sign is (−1)^popcount(i AND j)
&lt;/h2&gt;

&lt;p&gt;Because H acts independently on each qubit, H⊗³ is the tensor product of three 2×2 matrices. The entry at row i, column j is the product of the three corresponding single-qubit entries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H⊗³[i, j] = H[i₀, j₀] × H[i₁, j₁] × H[i₂, j₂]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each single-qubit factor equals +1 unless both the k-th bit of i &lt;strong&gt;and&lt;/strong&gt; the k-th bit of j are 1, in which case it equals −1. Multiplying all three:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sign(i, j) = (−1)^(i₀j₀ + i₁j₁ + i₂j₂) = (−1)^popcount(i AND j)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The rule in plain terms:&lt;/strong&gt; bitwise AND the row index and the column index, count the 1-bits, check parity. Even count → positive. Odd count → negative.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick verification:&lt;/strong&gt; row H|101⟩, column |011⟩&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;i (row)&lt;/th&gt;
&lt;th&gt;j (col)&lt;/th&gt;
&lt;th&gt;i AND j&lt;/th&gt;
&lt;th&gt;popcount&lt;/th&gt;
&lt;th&gt;Sign&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;101 (=5)&lt;/td&gt;
&lt;td&gt;011 (=3)&lt;/td&gt;
&lt;td&gt;001&lt;/td&gt;
&lt;td&gt;1 (odd)&lt;/td&gt;
&lt;td&gt;− ✓&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Matches the matrix in Section 5: row H|101⟩, column |011⟩ is indeed −.&lt;/p&gt;




&lt;h2&gt;
  
  
  7 · Connection to Grover's Diffusion Operator
&lt;/h2&gt;

&lt;p&gt;This matrix is the &lt;strong&gt;Hadamard Reference&lt;/strong&gt; used throughout the Grover's Algorithm walkthrough. The diffusion operator D = H⊗³ (2|0⟩⟨0| − I) H⊗³ works in three sub-steps, each directly using this matrix:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sub-step&lt;/th&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First H⊗³&lt;/td&gt;
&lt;td&gt;Maps computational basis → Hadamard basis&lt;/td&gt;
&lt;td&gt;Each amplitude spreads across all 8 columns via the sign table&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase flip&lt;/td&gt;
&lt;td&gt;2|0⟩⟨0|−I&lt;/td&gt;
&lt;td&gt;Keeps |000⟩ unchanged, negates all other states&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Second H⊗³&lt;/td&gt;
&lt;td&gt;Maps back to computational basis&lt;/td&gt;
&lt;td&gt;Routes constructive interference into the target state&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Without the sign structure of the Walsh-Hadamard matrix, neither the uniform superposition nor the diffusion step would work. The matrix is the silent engine behind Grover's quadratic speedup.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Quantum Series 2026 · Built with Qiskit 1.x&lt;/em&gt;&lt;/p&gt;

</description>
      <category>quantumcomputing</category>
      <category>mathematics</category>
      <category>qiskit</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Connecting an OpenClaw Bot to a Telegram Group Topic</title>
      <dc:creator>Malcolm Low</dc:creator>
      <pubDate>Sat, 16 May 2026 03:00:40 +0000</pubDate>
      <link>https://dev.to/malcolmlow/connecting-an-openclaw-bot-to-a-telegram-group-topic-1760</link>
      <guid>https://dev.to/malcolmlow/connecting-an-openclaw-bot-to-a-telegram-group-topic-1760</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://malcolmlow.net/2026/05/04/connecting-telegram-bot-openclaw/" rel="noopener noreferrer"&gt;malcolmlow.net&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Route OpenClaw agent notifications and responses through a private Telegram group using Topics for clean per-bot threading.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OpenClaw with Telegram bot&lt;/td&gt;
&lt;td&gt;OpenClaw must already be set up and working with a Telegram bot before proceeding. This guide only covers configuring it to post into a specific group topic.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Telegram account&lt;/td&gt;
&lt;td&gt;Active account with admin rights on a Telegram group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Telegram group with Topics&lt;/td&gt;
&lt;td&gt;A Telegram group with the Topics feature enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SingIDBot&lt;/td&gt;
&lt;td&gt;@SingIDBot — a custom bot built by the author, used to retrieve the chat ID and topic thread ID. Responds in Singlish, so don't be surprised by the personality.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Step 1 · Create a Topic for the Bot
&lt;/h2&gt;

&lt;p&gt;With Topics enabled on your group, create a dedicated topic for your OpenClaw bot to keep its messages isolated from other group activity.&lt;/p&gt;

&lt;p&gt;Tap the &lt;strong&gt;pencil / new topic&lt;/strong&gt; icon in your group and give it a clear name such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OpenClaw-Bot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the topic thread ID — you will retrieve this precisely in Step 2 using SingIDBot.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If the Topics toggle is not visible in your group settings, try adding 4–5 members to the group first. Telegram requires a minimum number of members before the Topics feature becomes available.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 2 · Get IDs from SingIDBot
&lt;/h2&gt;

&lt;p&gt;SingIDBot (@SingIDBot) returns the exact numeric IDs that OpenClaw needs: the group's chat ID and the topic's thread ID. See the full &lt;a href="https://dev.to/malcolmlow/singidbot-telegram-id-retrieval-bot-for-openclaw-topic-configuration-31g9-temp-slug-2669484"&gt;SingIDBot setup guide&lt;/a&gt; for how it works under the hood.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add &lt;strong&gt;@SingIDBot&lt;/strong&gt; to your group and grant it member access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Navigate into your OpenClaw-Bot topic&lt;/strong&gt; (not the General topic) before sending the command.&lt;/li&gt;
&lt;li&gt;Inside the topic, send: &lt;code&gt;/getids&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;SingIDBot will reply with a block like this:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;Chat&lt;/span&gt; &lt;span class="py"&gt;ID&lt;/span&gt;  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1001234567890&lt;/span&gt;
&lt;span class="err"&gt;Thread&lt;/span&gt; &lt;span class="py"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;42&lt;/span&gt;
&lt;span class="err"&gt;User&lt;/span&gt; &lt;span class="py"&gt;ID&lt;/span&gt;  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;987654321&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the &lt;strong&gt;Chat ID&lt;/strong&gt; and &lt;strong&gt;Thread ID&lt;/strong&gt;. You will pass them to OpenClaw in Step 4.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3 · Ask OpenClaw to Build the Config Tool
&lt;/h2&gt;

&lt;p&gt;Rather than editing the &lt;code&gt;.env&lt;/code&gt; file manually, ask the OpenClaw agent to write a Python tool that does it for you. The tool only needs the chat ID and topic thread ID — the bot token is already present in the &lt;code&gt;.env&lt;/code&gt; from initial setup.&lt;/p&gt;

&lt;p&gt;Use this prompt in your OpenClaw chat interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a Python tool called update_telegram_config that accepts
chat_id and topic_id as arguments and writes the values of
TELEGRAM_CHAT_ID and TELEGRAM_TOPIC_ID into the OpenClaw .env file.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenClaw will scaffold the tool, register it, and confirm it is ready to call. Proceed to Step 4 once the agent confirms the tool is available.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4 · Run the Tool and Reload OpenClaw
&lt;/h2&gt;

&lt;p&gt;With the IDs from Step 2 in hand, instruct OpenClaw to run the tool using your actual values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Run update_telegram_config with:
  chat_id = "-1001234567890"
  topic_id = "42"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the placeholder values with the IDs from Step 2. After the tool executes, reload OpenClaw so the new environment variables are picked up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# In your terminal (if running OpenClaw locally)&lt;/span&gt;
Ctrl+C       &lt;span class="c"&gt;# stop the current process&lt;/span&gt;
openclaw     &lt;span class="c"&gt;# restart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5 · Test the Setup
&lt;/h2&gt;

&lt;p&gt;Navigate into the &lt;strong&gt;OpenClaw-Bot&lt;/strong&gt; topic in your Telegram group and post any message. Wait for your OpenClaw bot to reply.&lt;/p&gt;

&lt;p&gt;If the group ID and topic ID have been configured correctly, your OpenClaw bot will respond directly inside the topic. If there is no response, double-check the IDs from Step 2 and rerun Step 4.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; By default, OpenClaw bots are configured to not respond to any message in a Telegram topic unless the correct group ID and topic ID are added into the config file. A missing or incorrect ID will result in complete silence from the bot.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  SingIDBot Quick Reference
&lt;/h2&gt;

&lt;p&gt;@SingIDBot is a custom Telegram bot built by the author. It does one job well: return the IDs you need for bot configuration. It also speaks Singlish, so expect replies like &lt;em&gt;"Wah, your chat ID here lah"&lt;/em&gt; — just read past the flavour text and grab your numbers.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it returns&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/getids&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Chat ID, Thread ID (topic), and your User ID&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Must be run inside the target topic&lt;/strong&gt; to get the correct Thread ID&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Also tested on Hermes Agent:&lt;/strong&gt; The same setup process works with the NousResearch Hermes Agent framework. The &lt;code&gt;update_telegram_config&lt;/code&gt; tool and environment variable structure are identical — simply run the same steps with Hermes Agent in place of OpenClaw.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your agent is now wired to a dedicated Telegram topic. Every notification, response, or alert it sends will land in the &lt;strong&gt;OpenClaw-Bot&lt;/strong&gt; thread, keeping it separate from general group activity. To add more agents or tools later, repeat Steps 1–4 with a new topic and a new set of environment variable names.&lt;/p&gt;

</description>
      <category>python</category>
      <category>telegram</category>
      <category>agenticai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>SingIDBot — Telegram ID Retrieval Bot for OpenClaw Topic Configuration</title>
      <dc:creator>Malcolm Low</dc:creator>
      <pubDate>Sat, 16 May 2026 02:58:42 +0000</pubDate>
      <link>https://dev.to/malcolmlow/singidbot-telegram-id-retrieval-bot-for-openclaw-topic-configuration-2e26</link>
      <guid>https://dev.to/malcolmlow/singidbot-telegram-id-retrieval-bot-for-openclaw-topic-configuration-2e26</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://malcolmlow.net/2026/05/08/singidbot-telegram-id-retrieval-bot-for-openclaw-topic-configuration/" rel="noopener noreferrer"&gt;malcolmlow.net&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you have been working through the &lt;a href="https://dev.to/malcolmlow/connecting-an-openclaw-bot-to-a-telegram-group-topic-1760"&gt;OpenClaw Telegram integration guide&lt;/a&gt;, you already know that one of the trickiest steps is obtaining the correct Chat ID and Topic Thread ID before you can configure your bot endpoints. Getting those IDs wrong means your bot silently sends messages into the void — no errors, no feedback, just nothing arriving in the right place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SingIDBot&lt;/strong&gt; was built specifically to solve that problem. Drop it into any Telegram chat or group, fire the &lt;code&gt;/getids&lt;/code&gt; command, and it instantly reports back the Chat ID and — crucially — the &lt;code&gt;message_thread_id&lt;/code&gt; for whichever topic the command was sent from.&lt;/p&gt;

&lt;p&gt;Beyond the ID retrieval utility, SingIDBot has a second personality: it responds to free-text messages in Singlish — Singapore's beloved colloquial English creole — cycling through randomised phrases like &lt;em&gt;"Aiyoh, you finally came! Welcome lah!"&lt;/em&gt; and &lt;em&gt;"Wah, interesting leh. Tell me more can?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This guide walks through the complete source code, explains each architectural decision, and covers deployment on PythonAnywhere including the free-tier network restrictions you will inevitably hit.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Python 3.10+&lt;/td&gt;
&lt;td&gt;Required for python-telegram-bot v20+ async support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;python-telegram-bot v20+&lt;/td&gt;
&lt;td&gt;The async-native version. Install with &lt;code&gt;pip install python-telegram-bot&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Telegram Bot Token&lt;/td&gt;
&lt;td&gt;Create via &lt;a class="mentioned-user" href="https://dev.to/botfather"&gt;@botfather&lt;/a&gt; — send &lt;code&gt;/newbot&lt;/code&gt; and copy the token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PythonAnywhere account&lt;/td&gt;
&lt;td&gt;Free Beginner account is sufficient to run and test the bot&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Section 1 — What SingIDBot Does
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The message_thread_id Mechanism
&lt;/h3&gt;

&lt;p&gt;Telegram supergroups can be divided into named Topics, each identified by a &lt;code&gt;message_thread_id&lt;/code&gt;. When a message is sent inside a topic, Telegram attaches this integer to the message object. When sent outside any topic, the field is absent entirely — not zero, not null, but genuinely missing.&lt;/p&gt;

&lt;p&gt;This is the exact value OpenClaw requires to route notifications to the correct topic thread. SingIDBot's &lt;code&gt;/getids&lt;/code&gt; command reads &lt;code&gt;message_thread_id&lt;/code&gt; from the incoming message and reports it in plain text for direct copy-paste into your configuration.&lt;/p&gt;

&lt;p&gt;Because the field may be absent, the code uses &lt;code&gt;getattr(update.effective_message, 'message_thread_id', None)&lt;/code&gt; rather than direct attribute access, which would raise an &lt;code&gt;AttributeError&lt;/code&gt; in non-topic contexts.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Singlish Responder
&lt;/h3&gt;

&lt;p&gt;Any free-text message (not a command) triggers the &lt;code&gt;singlish_chat&lt;/code&gt; handler. It classifies the message into greeting, thanks, or default using keyword matching, then picks a random phrase from the corresponding pool.&lt;/p&gt;




&lt;h2&gt;
  
  
  Section 2 — Code Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 Logging Setup
&lt;/h3&gt;

&lt;p&gt;Two handlers run simultaneously: a &lt;code&gt;FileHandler&lt;/code&gt; writing UTF-8 lines to &lt;code&gt;singidbot.log&lt;/code&gt;, and a &lt;code&gt;StreamHandler&lt;/code&gt; for the console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;LOG_FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;singidbot.log&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%(asctime)s [%(levelname)s] %(name)s: %(message)s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FileHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOG_FILE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; The &lt;code&gt;encoding="utf-8"&lt;/code&gt; argument is essential if any Telegram usernames contain non-ASCII characters. Without it, a single emoji in a username can crash the logger with a &lt;code&gt;UnicodeEncodeError&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2.2 Singlish Response Bank
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;SINGLISH_RESPONSES&lt;/code&gt; maps category keys to phrase lists. &lt;code&gt;get_singlish_response()&lt;/code&gt; uses &lt;code&gt;dict.get()&lt;/code&gt; with a &lt;code&gt;"default"&lt;/code&gt; fallback so unknown categories never raise a &lt;code&gt;KeyError&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;SINGLISH_RESPONSES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;greeting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Wah, you here ah! Come come, sit down lah!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Eh hello! Long time no see, how are you?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Aiyoh, you finally came! Welcome lah!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Oi! Good to see you sia. What can I help you?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thanks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Aiyah, no need to thank one lah!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Wah, so polite! Welcome lah, anytime!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No problem one! Next time also can help you.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Eh, paiseh lah - that is what I am here for!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hah? Can repeat or not? I blur blur lah.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Wah, interesting leh. Tell me more can?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Aiyoh, I also dunno how to answer you sia.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Got it lah! But I not so sure about that one.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Eh, you very clever leh. I learn from you!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_singlish_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SINGLISH_RESPONSES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SINGLISH_RESPONSES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.3 log_activity() Async Helper
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log_activity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[%s] event=%s user=%s metadata=%s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.4 /start and /help Handlers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;effective_user&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;log_activity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;START&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chat_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;effective_chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_singlish_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;greeting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;friend&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;welcome_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

Eh &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, I am *SingIDBot* lah!

&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Commands:
- /start
- /help
- /getids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reply_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;welcome_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parse_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Markdown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.5 /getids Handler
&lt;/h3&gt;

&lt;p&gt;The key line is the &lt;code&gt;getattr&lt;/code&gt; call. Telegram only populates &lt;code&gt;message_thread_id&lt;/code&gt; when a message arrives inside a topic thread — in a regular chat the attribute simply does not exist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_ids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;effective_user&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;log_activity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ID_RETRIEVAL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chat_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;effective_chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;chat_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;effective_chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;
    &lt;span class="n"&gt;topic_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;effective_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message_thread_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Chat/Group ID: `&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;chat_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;`
&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;topic_id&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Topic ID: `&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;topic_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;`
(This ID confirms the specific topic thread)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Topic ID: Not available
(Topics may not be enabled)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;

Tip: Record these IDs for configuring bot endpoints!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reply_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parse_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Markdown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reply_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;get_singlish_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;thanks&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; Lah!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.6 singlish_chat Handler
&lt;/h3&gt;

&lt;p&gt;Registered with &lt;code&gt;filters.TEXT&lt;/code&gt; and &lt;code&gt;~filters.COMMAND&lt;/code&gt;. A guard clause checks if the sender is the bot itself to prevent infinite reply loops.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;singlish_chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;effective_user&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;log_activity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MESSAGE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text_preview&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;
            &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;effective_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="n"&gt;user_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user_text&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thanks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thank&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;appreciate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
        &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thanks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user_text&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hey&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;oi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wah&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;alamak&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
        &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;greeting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reply_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get_singlish_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.7 error_handler — Two-Tier Approach
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;error_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;error_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;
        &lt;span class="n"&gt;error_msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ProxyError&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;error_msg&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NetworkError&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;error_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Network error (transient): %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error_msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Conflict&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;error_name&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;terminated by other getUpdates&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;error_msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Conflict error (duplicate instance?): %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error_msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unhandled exception: %s: %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="n"&gt;error_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error_msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc_info&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.8 main() — Builder Chain and Handler Registration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_BOT_TOKEN_HERE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOKEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect_timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CommandHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;start&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CommandHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;help&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help_command&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CommandHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;getids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_ids&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MessageHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COMMAND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;singlish_chat&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_error_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error_handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--- SingIDBot Initializing ---&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_polling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allowed_updates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ALL_TYPES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Section 3 — Deployment on PythonAnywhere
&lt;/h2&gt;

&lt;p&gt;Upload &lt;code&gt;singidbot.py&lt;/code&gt; via the Files tab, open a Bash console, and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;python-telegram-bot &lt;span class="nt"&gt;--upgrade&lt;/span&gt;
python singidbot.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Free-Tier Proxy Restriction
&lt;/h3&gt;

&lt;p&gt;Free accounts route outbound traffic through a proxy that does not whitelist &lt;code&gt;api.telegram.org&lt;/code&gt;. Outbound &lt;code&gt;sendMessage&lt;/code&gt; calls can fail with &lt;code&gt;httpx.ProxyError: 503 Service Unavailable&lt;/code&gt;. Inbound polling via &lt;code&gt;getUpdates&lt;/code&gt; works fine — it is only the reply direction that is intermittently blocked.&lt;/p&gt;

&lt;p&gt;In practice across four live sessions totalling over 5 hours, only 2 ProxyErrors occurred in 1800+ polling cycles.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Options if you need reliable reply delivery:&lt;/strong&gt; Upgrade to a paid PythonAnywhere plan, or switch from polling to webhook mode via PythonAnywhere's WSGI layer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Avoiding Duplicate Instance Conflicts
&lt;/h3&gt;

&lt;p&gt;Telegram only allows one active &lt;code&gt;getUpdates&lt;/code&gt; poller per token. Always kill the old process before restarting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pkill &lt;span class="nt"&gt;-f&lt;/span&gt; singidbot.py
pgrep &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; singidbot
python singidbot.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Section 4 — Log Analysis
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Session&lt;/th&gt;
&lt;th&gt;Duration&lt;/th&gt;
&lt;th&gt;Key Events&lt;/th&gt;
&lt;th&gt;Errors&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Session 1&lt;/td&gt;
&lt;td&gt;~2 min&lt;/td&gt;
&lt;td&gt;First run. &lt;code&gt;/getids&lt;/code&gt; succeeded returning Chat ID 5024469893.&lt;/td&gt;
&lt;td&gt;1 ProxyError (no error handler yet)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Session 2&lt;/td&gt;
&lt;td&gt;~3 min&lt;/td&gt;
&lt;td&gt;Error handler added. &lt;code&gt;/help&lt;/code&gt; ProxyError suppressed to WARNING.&lt;/td&gt;
&lt;td&gt;1 ProxyError (WARNING only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Session 3&lt;/td&gt;
&lt;td&gt;~14 min&lt;/td&gt;
&lt;td&gt;Extended run. 47 consecutive clean polling cycles.&lt;/td&gt;
&lt;td&gt;1 ProxyError (WARNING only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Session 4&lt;/td&gt;
&lt;td&gt;~5 hours&lt;/td&gt;
&lt;td&gt;1800+ log lines. Clean polling throughout. No conflicts.&lt;/td&gt;
&lt;td&gt;2 ProxyErrors total&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;SingIDBot is production-stable on the free tier. The intermittent ProxyError is a platform constraint, not a code defect.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it returns&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/start&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Personalised Singlish greeting and command list&lt;/td&gt;
&lt;td&gt;Works in any chat context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/help&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List of all available commands&lt;/td&gt;
&lt;td&gt;Works in any chat context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/getids&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Chat ID and Topic Thread ID (if inside a topic)&lt;/td&gt;
&lt;td&gt;Must be run inside the target topic to get a valid Thread ID&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>python</category>
      <category>telegram</category>
      <category>agenticai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Word Embeddings Explained: The Math Behind AI, LLMs, and Chatbots</title>
      <dc:creator>Malcolm Low</dc:creator>
      <pubDate>Sat, 16 May 2026 02:55:33 +0000</pubDate>
      <link>https://dev.to/malcolmlow/word-embeddings-explained-the-math-behind-ai-llms-and-chatbots-41lb</link>
      <guid>https://dev.to/malcolmlow/word-embeddings-explained-the-math-behind-ai-llms-and-chatbots-41lb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://malcolmlow.net/2026/05/11/word-embeddings-explained-the-math-behind-ai-llms-and-chatbots/" rel="noopener noreferrer"&gt;malcolmlow.net&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When a search engine retrieves a document about &lt;strong&gt;automobiles&lt;/strong&gt; in response to a query about &lt;strong&gt;cars&lt;/strong&gt;, it is not matching text character by character. Somewhere beneath the interface, the system understands that these two words are semantically related. The mechanism behind that understanding is the &lt;strong&gt;word embedding&lt;/strong&gt; — and once you see the geometry, you cannot unsee it.&lt;/p&gt;

&lt;p&gt;This article walks through the key mathematical operations that make embeddings work: distance, similarity, arithmetic, scaling, and the dot product. Each concept is illustrated with concrete numerical vectors so the math is visible, not just described. Real embeddings typically use hundreds of dimensions; the 3- and 4-dimensional examples here preserve all the structure while staying readable on a page.&lt;/p&gt;




&lt;h2&gt;
  
  
  1 · What is a Word Embedding?
&lt;/h2&gt;

&lt;p&gt;A word embedding is a representation of a word as a &lt;strong&gt;vector&lt;/strong&gt; — an ordered list of numbers — in a high-dimensional space. A typical embedding model might use 300 dimensions, so the word &lt;em&gt;cat&lt;/em&gt; becomes a point with 300 coordinates. The key insight: &lt;strong&gt;the position of that point encodes meaning&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is what researchers call a &lt;strong&gt;semantic space&lt;/strong&gt;. Words with related meanings end up positioned close to each other. &lt;em&gt;King&lt;/em&gt; and &lt;em&gt;Queen&lt;/em&gt; live near each other. &lt;em&gt;Paris&lt;/em&gt; and &lt;em&gt;London&lt;/em&gt; live near each other. &lt;em&gt;Bicycle&lt;/em&gt; and &lt;em&gt;democracy&lt;/em&gt; live far apart.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: 4-dimensional vectors (simplified from real 300-dim embeddings)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vec("King")  = [ 0.9,  0.7,  0.4, +0.6 ]
vec("Queen") = [ 0.9,  0.7,  0.4, -0.6 ]
vec("Man")   = [ 0.5,  0.3,  0.1, +0.8 ]
vec("Woman") = [ 0.5,  0.3,  0.1, -0.8 ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first three dimensions encode royalty, authority, and age. The fourth dimension encodes gender: positive = masculine, negative = feminine.&lt;/p&gt;




&lt;h2&gt;
  
  
  2 · The Geometry of Meaning: Distance and Similarity
&lt;/h2&gt;

&lt;p&gt;Once words are points in space, we need a way to measure how close they are. Two approaches dominate: Euclidean distance and cosine similarity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Temperature vectors (3 dimensions)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vec("Hot")  = [ 1.0,  0.8,  0.6 ]
vec("Warm") = [ 0.8,  0.6,  0.4 ]
vec("Cold") = [-0.6,  0.4, -0.8 ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.1 Euclidean Distance
&lt;/h3&gt;

&lt;p&gt;The straight-line gap between the tips of two vectors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;d(a, b) = √ Σᵢ (aᵢ − bᵢ)²
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Worked example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;d(Hot, Warm) = √[(1.0-0.8)² + (0.8-0.6)² + (0.6-0.4)²]
             = √[0.04 + 0.04 + 0.04] = √0.12 ≈ 0.346  ← small: close together

d(Hot, Cold) = √[(1.0-(-0.6))² + (0.8-0.4)² + (0.6-(-0.8))²]
             = √[2.56 + 0.16 + 1.96] = √4.68 ≈ 2.163  ← large: far apart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.2 Cosine Similarity — The Industry Standard
&lt;/h3&gt;

&lt;p&gt;In practice, NLP systems almost universally prefer &lt;strong&gt;cosine similarity&lt;/strong&gt;. It ignores vector &lt;em&gt;length&lt;/em&gt; entirely and focuses only on the &lt;strong&gt;angle&lt;/strong&gt; between them — two vectors pointing the same direction score 1.0 regardless of magnitude.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cos(θ) = (a · b) / (‖a‖ × ‖b‖)

Range: −1 (opposite) → 0 (orthogonal) → +1 (identical direction)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Worked example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;‖Hot‖  = √(1.0² + 0.8² + 0.6²) = √2.00 ≈ 1.414
‖Warm‖ = √(0.8² + 0.6² + 0.4²) = √1.16 ≈ 1.077
‖Cold‖ = √(0.6² + 0.4² + 0.8²) = √1.16 ≈ 1.077

dot(Hot, Warm) = (1.0)(0.8) + (0.8)(0.6) + (0.6)(0.4) = 1.52
cos(Hot, Warm) = 1.52 / (1.414 × 1.077) ≈ +0.998   ← nearly identical direction

dot(Hot, Cold) = (1.0)(-0.6) + (0.8)(0.4) + (0.6)(-0.8) = -0.76
cos(Hot, Cold) = -0.76 / (1.414 × 1.077) ≈ -0.499  ← opposite directions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Word Pair&lt;/th&gt;
&lt;th&gt;Euclidean d&lt;/th&gt;
&lt;th&gt;cos(θ)&lt;/th&gt;
&lt;th&gt;Interpretation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hot vs Warm&lt;/td&gt;
&lt;td&gt;0.346&lt;/td&gt;
&lt;td&gt;+0.998&lt;/td&gt;
&lt;td&gt;Nearly identical direction — closely related&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hot vs Cold&lt;/td&gt;
&lt;td&gt;2.163&lt;/td&gt;
&lt;td&gt;−0.499&lt;/td&gt;
&lt;td&gt;Opposite directions — antonyms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  3 · Vector Arithmetic: Meaning You Can Add and Subtract
&lt;/h2&gt;

&lt;p&gt;Because words are vectors, you can perform arithmetic on them — and the results are semantically meaningful. The most famous example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vec("King") − vec("Man") + vec("Woman") ≈ vec("Queen")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Worked example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;King  = [ 0.9,  0.7,  0.4, +0.6 ]
Man   = [ 0.5,  0.3,  0.1, +0.8 ]
Woman = [ 0.5,  0.3,  0.1, -0.8 ]

King − Man = [ 0.4,  0.4,  0.3, -0.2 ]
+ Woman    = [ 0.9,  0.7,  0.4, -1.0 ]

d(result, Queen)  ≈ 0.400  ← nearest
d(result, Woman)  ≈ 0.671
d(result, King)   = 1.600
cos(result, Queen) ≈ 0.974  ← highest cosine similarity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happened geometrically? Subtracting &lt;em&gt;Man&lt;/em&gt; stripped out the gender dimension, leaving the royalty structure intact. Adding &lt;em&gt;Woman&lt;/em&gt; injected the feminine gender value. The result sits 0.4 units from &lt;em&gt;Queen&lt;/em&gt; — the nearest word in this vocabulary.&lt;/p&gt;




&lt;h2&gt;
  
  
  4 · Scalar Multiplication and Division: Changing Intensity
&lt;/h2&gt;

&lt;p&gt;Multiplying or dividing a vector by a scalar changes its &lt;strong&gt;magnitude&lt;/strong&gt; without changing its &lt;strong&gt;direction&lt;/strong&gt;. This maps onto the idea of degree in language — &lt;em&gt;Tiny&lt;/em&gt;, &lt;em&gt;Large&lt;/em&gt;, and &lt;em&gt;Gigantic&lt;/em&gt; all point in roughly the same semantic direction, at different intensities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Size vectors (3 dimensions)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vec("Tiny")     = [ 0.10,  0.20,  0.10 ]
vec("Large")    = [ 0.50,  0.70,  0.40 ]
vec("Gigantic") = [ 1.10,  1.50,  0.90 ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Worked example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Large × 2   = [ 1.00, 1.40, 0.80 ]
vec("Gigantic") = [ 1.10, 1.50, 0.90 ]
d(Large × 2, Gigantic) ≈ 0.173  ← very close

Large × 0.2 = [ 0.10, 0.14, 0.08 ]
vec("Tiny")     = [ 0.10, 0.20, 0.10 ]
d(Large × 0.2, Tiny) ≈ 0.063   ← very close

Loud ÷ 2 lands near "Soft" — direction unchanged, intensity halved.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key intuition:&lt;/strong&gt; Scalar operations change &lt;em&gt;how much&lt;/em&gt; of something a vector represents, without changing &lt;em&gt;what kind&lt;/em&gt; of thing it represents.&lt;/p&gt;




&lt;h2&gt;
  
  
  5 · The Dot Product: Agreement and Magnitude Together
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a · b = Σᵢ (aᵢ × bᵢ) = a₁b₁ + a₂b₂ + … + aₙbₙ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dot product captures two things simultaneously: the &lt;strong&gt;direction of agreement&lt;/strong&gt; and the &lt;strong&gt;combined magnitude&lt;/strong&gt;. Cosine similarity captures only the first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Worked example — Very Loud vs A Little Loud:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vec("A Little Loud") = [ 0.30, 0.40, 0.20 ]  |magnitude| = 0.539
vec("Very Loud")     = [ 0.90, 1.20, 0.60 ]  |magnitude| = 1.616

dot(AL, VL) = (0.3)(0.9) + (0.4)(1.2) + (0.2)(0.6) = 0.87
cos(AL, VL) = 0.87 / (0.539 × 1.616) ≈ 1.000  ← perfect alignment

AL · AL = 0.09 + 0.16 + 0.04 = 0.29
VL · VL = 0.81 + 1.44 + 0.36 = 2.61
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Comparison&lt;/th&gt;
&lt;th&gt;Magnitude&lt;/th&gt;
&lt;th&gt;cos(θ)&lt;/th&gt;
&lt;th&gt;v · v&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A Little Loud&lt;/td&gt;
&lt;td&gt;0.539&lt;/td&gt;
&lt;td&gt;1.000&lt;/td&gt;
&lt;td&gt;0.29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Very Loud&lt;/td&gt;
&lt;td&gt;1.616&lt;/td&gt;
&lt;td&gt;1.000&lt;/td&gt;
&lt;td&gt;2.61&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both are perfectly collinear — cosine similarity is 1.0 in both cases. But the dot products are 0.29 vs 2.61, a 9× difference. This is why recommendation systems and attention mechanisms in transformer models often prefer raw dot products: when you want to know not just whether a document is &lt;em&gt;relevant&lt;/em&gt; but also how &lt;em&gt;prominently&lt;/em&gt; it discusses a topic, the dot product gives you both dimensions at once.&lt;/p&gt;




&lt;h2&gt;
  
  
  6 · Practical Applications
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Search engines&lt;/strong&gt; convert your query into a vector and retrieve documents whose vectors are nearest to it — using cosine similarity to rank by relevance regardless of exact word match. When you search for &lt;em&gt;car insurance&lt;/em&gt; and get results about &lt;em&gt;vehicle coverage&lt;/em&gt;, that's nearest-neighbour lookup in embedding space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommendation systems&lt;/strong&gt; represent your interests as a vector computed from your history, then find products whose vectors are closest. The dot product is particularly useful here: a highly-relevant item with a large magnitude will score higher than a mildly-relevant item even if they point in the same direction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Large language models&lt;/strong&gt; use the scaled dot product directly inside the attention mechanism. For every token, a query vector and a set of key vectors are compared via dot product to determine which parts of the context deserve attention — a direct descendant of the arithmetic in Section 5.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference: Embedding Operations
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Formula&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Euclidean Distance&lt;/td&gt;
&lt;td&gt;√(Σ(aᵢ−bᵢ)²)&lt;/td&gt;
&lt;td&gt;d(Hot,Warm)=0.346 / d(Hot,Cold)=2.163&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cosine Similarity&lt;/td&gt;
&lt;td&gt;(a·b)/(‖a‖×‖b‖)&lt;/td&gt;
&lt;td&gt;cos(Hot,Warm)=+0.998 / cos(Hot,Cold)=-0.499&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vector Arithmetic&lt;/td&gt;
&lt;td&gt;a ± b&lt;/td&gt;
&lt;td&gt;King−Man+Woman → nearest Queen (d=0.400)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scalar Multiplication&lt;/td&gt;
&lt;td&gt;λ · a&lt;/td&gt;
&lt;td&gt;Large×2 → near Gigantic / Loud÷2 → near Soft&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dot Product&lt;/td&gt;
&lt;td&gt;a·b = Σaᵢbᵢ&lt;/td&gt;
&lt;td&gt;cos=1.00 for both; dot 0.29 (soft) vs 2.61 (loud)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>nlp</category>
      <category>mathematics</category>
    </item>
    <item>
      <title>Agentic Code Generation with OpenAI Codex CLI — A Knight's Tour Walkthrough</title>
      <dc:creator>Malcolm Low</dc:creator>
      <pubDate>Sat, 16 May 2026 02:51:42 +0000</pubDate>
      <link>https://dev.to/malcolmlow/agentic-code-generation-with-openai-codex-cli-a-knights-tour-walkthrough-ehj</link>
      <guid>https://dev.to/malcolmlow/agentic-code-generation-with-openai-codex-cli-a-knights-tour-walkthrough-ehj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://malcolmlow.net/2026/05/15/knights-tour-codex-cli/" rel="noopener noreferrer"&gt;malcolmlow.net&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A step-by-step walkthrough of using OpenAI's agentic coding tool to scaffold, solve, test, and visualise the classic Knight's Tour chess problem — entirely through natural language prompts.&lt;/p&gt;

&lt;p&gt;This post assumes you have Codex CLI installed and authenticated. We'll be working in three phases, each driven by a carefully crafted Codex prompt.&lt;/p&gt;




&lt;h2&gt;
  
  
  ♞ What is the Knight's Tour Problem?
&lt;/h2&gt;

&lt;p&gt;The Knight's Tour is a classic puzzle from combinatorics and graph theory: given an n×n chessboard and a knight placed on any starting square, can the knight visit every square on the board exactly once using only valid knight moves? A knight moves in an L-shape — two squares in one direction and one square perpendicular, giving it up to eight possible moves from any position.&lt;/p&gt;

&lt;p&gt;The problem has been studied for over a thousand years. Arab mathematicians documented it as early as the 9th century, and Leonhard Euler conducted a systematic mathematical analysis in 1759. There are two variants: an &lt;strong&gt;open tour&lt;/strong&gt;, where the starting and ending squares differ, and a &lt;strong&gt;closed (re-entrant) tour&lt;/strong&gt;, where the knight can return to its starting square in one move. On the standard 8×8 board, there are over 26 trillion distinct open tours.&lt;/p&gt;

&lt;p&gt;From an algorithmic standpoint, the Knight's Tour is a special case of the &lt;strong&gt;Hamiltonian path problem&lt;/strong&gt; on a graph, where each square is a node and edges connect squares reachable by a knight move. Finding a Hamiltonian path is NP-complete in general, but the regular structure of the chessboard makes efficient heuristics possible.&lt;/p&gt;

&lt;p&gt;The most well-known heuristic is &lt;strong&gt;Warnsdorff's rule&lt;/strong&gt; (H.C. von Warnsdorff, 1823): at each step, move to the unvisited square that has the fewest onward moves. This greedy approach runs in linear time relative to the number of squares and finds a tour almost always on boards of size 5×5 and above.&lt;/p&gt;




&lt;h2&gt;
  
  
  🗺️ What We're Building
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;What Codex Builds&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Phase 1&lt;/td&gt;
&lt;td&gt;Core solver using Warnsdorff's heuristic&lt;/td&gt;
&lt;td&gt;CLI app, ASCII board output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 2&lt;/td&gt;
&lt;td&gt;Pytest test suite and colourised terminal output&lt;/td&gt;
&lt;td&gt;ANSI colour board, passing tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 3&lt;/td&gt;
&lt;td&gt;Flask web app with animated HTML canvas&lt;/td&gt;
&lt;td&gt;Interactive browser visualisation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ⚙️ Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Codex CLI installed (&lt;code&gt;brew install --cask codex&lt;/code&gt; or &lt;code&gt;npm i -g @openai/codex&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Authenticated with a ChatGPT Plus/Pro account or an OpenAI API key&lt;/li&gt;
&lt;li&gt;Python 3.10+ available in your shell&lt;/li&gt;
&lt;li&gt;Git installed on your machine&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📁 Project Setup
&lt;/h2&gt;

&lt;p&gt;We'll use Git throughout this guide as a safety net. Configure your identity first if needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name  &lt;span class="s2"&gt;"Your Name"&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email &lt;span class="s2"&gt;"you@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the project directory and initialise the repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;knights-tour &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;knights-tour
git init
git commit &lt;span class="nt"&gt;--allow-empty&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"initial commit"&lt;/span&gt;
codex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the TUI loads, generate an &lt;code&gt;AGENTS.md&lt;/code&gt; file first. It acts as a standing project-level system prompt — Codex reads it automatically at the start of every future session.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📝 Codex Prompt — Generate AGENTS.md&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"Create an AGENTS.md file in the project root for a Python CLI and web application project. Include the following standing instructions: use Python 3.10+ with type hints throughout; place all tests in a /tests directory using pytest; never use global mutable state; prefer functions over classes unless OOP is genuinely the better fit; handle all CLI arguments with argparse; use Flask for any web routes; keep each module focused on a single responsibility."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Why prompt Codex to write AGENTS.md instead of writing it yourself?&lt;/strong&gt; You describe your intent conversationally rather than worrying about format, and it sets the right mental model for the rest of the guide. You can update it at any time: &lt;em&gt;"Add a rule that all functions must have docstrings"&lt;/em&gt; — Codex will edit the file in place.&lt;/p&gt;




&lt;h2&gt;
  
  
  Phase 1 — Core Solver
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📝 Codex Prompt — Phase 1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"Create a Python CLI app that solves the Knight's Tour problem. Use Warnsdorff's heuristic: at each step, move to the unvisited square with the fewest onward moves. The board size and starting position (row, col) should be configurable via argparse with defaults of n=8, row=0, col=0. The solver should return None if no tour is found. Display the completed board as a grid of move numbers, right-aligned. Save the solver logic in knight_tour.py and the entry point in main.py. Include a requirements.txt and a .gitignore for Python."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's a simplified version of what the generated &lt;code&gt;knight_tour.py&lt;/code&gt; looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MOVES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_neighbours&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;dy&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;MOVES&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;dy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
            &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;visited&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;board&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;start_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_y&lt;/span&gt;
    &lt;span class="n"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;neighbours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_neighbours&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;neighbours&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;neighbours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get_neighbours&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="n"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it to verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 main.py &lt;span class="nt"&gt;--size&lt;/span&gt; 8 &lt;span class="nt"&gt;--row&lt;/span&gt; 0 &lt;span class="nt"&gt;--col&lt;/span&gt; 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Approval Flow:&lt;/strong&gt; In Codex's default Auto mode, press &lt;strong&gt;A&lt;/strong&gt; to accept or &lt;strong&gt;R&lt;/strong&gt; to reject each diff. If Codex proposes something you don't want, reject and follow up with a corrective prompt — it retains full context.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Phase 2 — Tests &amp;amp; Colourised Output
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📝 Codex Prompt — Phase 2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"Now add two things. First, create a test suite in tests/test_knight_tour.py using pytest. Test that: (1) solve() returns a valid tour where every integer from 0 to n²−1 appears exactly once, (2) consecutive moves are a valid knight's move apart, (3) solve() returns None for n=2 which has no solution. Second, add a new function print_coloured_board() in knight_tour.py that uses ANSI escape codes to colour the board — alternate between a light and dark background for a chess-style pattern, with white text for the move numbers. Call it from main.py instead of format_board() when --colour flag is passed."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Key tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;knight_tour&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;solve&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_valid_knight_move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

&lt;span class="nd"&gt;@pytest.mark.parametrize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;n,r,c&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_valid_tour&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;board&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;flat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;flat&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_no_solution_n2&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install pytest and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip3 &lt;span class="nb"&gt;install &lt;/span&gt;pytest
pytest tests/ &lt;span class="nt"&gt;-v&lt;/span&gt;
python3 main.py &lt;span class="nt"&gt;--size&lt;/span&gt; 8 &lt;span class="nt"&gt;--colour&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Phase 3 — Flask Web App with Animated Visualisation
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📝 Codex Prompt — Phase 3&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"Add a Flask web app in app.py. It needs two routes: GET / serves a single-page HTML form where users can input board size (5–10) and starting row/col. POST /solve accepts these inputs, runs the solver, and returns the board as JSON. The HTML page should also contain a JavaScript canvas visualisation that animates the knight's path one move at a time — draw the board as a grid, colour visited squares progressively, and draw a ♞ symbol on the current square. Add flask to requirements.txt."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The key backend endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render_template_string&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;knight_tour&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;solve&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/solve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;solve_tour&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;row&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;col&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Board size must be between 5 and 10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;
    &lt;span class="n"&gt;board&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No solution found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;422&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;board&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip3 &lt;span class="nb"&gt;install &lt;/span&gt;flask
python3 app.py
&lt;span class="c"&gt;# Visit http://localhost:5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔄 Iterating Further — More Prompt Ideas
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Goal&lt;/th&gt;
&lt;th&gt;Follow-up Prompt&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Speed comparison&lt;/td&gt;
&lt;td&gt;"Add a backtracking solver as an alternative to Warnsdorff's. Add a --solver flag to switch between them, and time both with Python's timeit."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Export result&lt;/td&gt;
&lt;td&gt;"Add a --export flag to main.py that saves the board as a CSV and a PNG using matplotlib, with the knight path drawn as a line."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User clicks board&lt;/td&gt;
&lt;td&gt;"Update the web app so users click a cell on the canvas to set the starting position instead of using the form fields."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code review&lt;/td&gt;
&lt;td&gt;"Review the current codebase for edge cases, type annotation completeness, and any issues with input validation in app.py."&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ✅ Effective Prompting Tips for Codex
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tip&lt;/th&gt;
&lt;th&gt;Why It Helps&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Name your files explicitly&lt;/td&gt;
&lt;td&gt;Codex won't guess at naming conventions — "save to knight_tour.py" prevents arbitrary filenames.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Specify what None/failure means&lt;/td&gt;
&lt;td&gt;Without "return None if no tour is found," Codex might raise an exception instead.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bundle related changes in one prompt&lt;/td&gt;
&lt;td&gt;Codex handles multi-file tasks well when given in a single cohesive prompt.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep sessions alive for follow-ups&lt;/td&gt;
&lt;td&gt;Staying in the same session means Codex retains full context — no re-explaining.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use AGENTS.md for standing rules&lt;/td&gt;
&lt;td&gt;Anything you'd say in every prompt belongs in AGENTS.md. It keeps prompts shorter and style consistent.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📁 Final Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;knights-tour/
├── AGENTS.md
├── .gitignore
├── requirements.txt      ← flask
├── knight_tour.py        ← solver + display logic
├── main.py               ← CLI entry point
├── app.py                ← Flask web app
└── tests/
    └── test_knight_tour.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow rhythm: each Codex prompt builds on the last without re-explaining context, and AGENTS.md silently enforces project conventions. The three phases took roughly 15 minutes end-to-end, most of which was reviewing diffs and running tests rather than writing code.&lt;/p&gt;

&lt;p&gt;The Knight's Tour is just the illustration. The same prompt-iterate-commit loop applies to any project — and the more you invest in a good AGENTS.md upfront, the more useful each Codex session becomes.&lt;/p&gt;

</description>
      <category>agenticai</category>
      <category>codex</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Eigenvectors and Eigenvalues: The Quantum Computing Secret Sauce</title>
      <dc:creator>Malcolm Low</dc:creator>
      <pubDate>Sun, 26 Apr 2026 15:44:05 +0000</pubDate>
      <link>https://dev.to/malcolmlow/eigenvectors-and-eigenvalues-the-quantum-computing-secret-sauce-no-phd-required-2dpa</link>
      <guid>https://dev.to/malcolmlow/eigenvectors-and-eigenvalues-the-quantum-computing-secret-sauce-no-phd-required-2dpa</guid>
      <description>&lt;h1&gt;
  
  
  Eigenvectors and Eigenvalues: The Quantum Computing Secret Sauce
&lt;/h1&gt;

&lt;p&gt;Ever wondered what makes quantum computers so powerful? At the heart of quantum mechanics—and thus quantum computing—lies a pair of mathematical twins: &lt;strong&gt;eigenvectors&lt;/strong&gt; and &lt;strong&gt;eigenvalues&lt;/strong&gt;. Don’t worry, no advanced linear algebra background needed. Let’s break it down with everyday analogies.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Eigenvectors and Eigenvalues? (The Simple Version)
&lt;/h2&gt;

&lt;p&gt;Imagine a spinning top. No matter how you tilt it, if you spin it around its symmetry axis, it just spins faster or slower—it doesn’t wobble. That axis is like an &lt;strong&gt;eigenvector&lt;/strong&gt;: a special direction where a transformation (here, spinning) only stretches or shrinks the object, never changes its direction. The amount of stretching/shrinking is the &lt;strong&gt;eigenvalue&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In math terms: if you have a square matrix &lt;code&gt;A&lt;/code&gt; (representing a transformation) and a vector &lt;code&gt;v&lt;/code&gt;, then&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A v = λ v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;v&lt;/code&gt; is an eigenvector, &lt;code&gt;λ&lt;/code&gt; (lambda) is its eigenvalue. The transformation &lt;code&gt;A&lt;/code&gt; acting on &lt;code&gt;v&lt;/code&gt; just scales it by &lt;code&gt;λ&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Finding Eigenvalues and Eigenvectors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s compute the eigenvalues and eigenvectors for a simple matrix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A = [2  1]
    [1  2]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 1: Set up the characteristic equation&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
We want to find scalars λ and non-zero vectors v such that A v = λ v.&lt;br&gt;&lt;br&gt;
Rearranging: (A - λI) v = 0.&lt;br&gt;&lt;br&gt;
For a non-zero solution v to exist, the matrix (A - λI) must be singular,&lt;br&gt;&lt;br&gt;
meaning its determinant equals zero: det(A - λI) = 0.&lt;br&gt;&lt;br&gt;
Solve det(A - λI) = 0:&lt;br&gt;&lt;br&gt;
det([[2-λ, 1], [1, 2-λ]]) = (2-λ)² - 1 = 0&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Solve for λ&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Expand: λ² - 4λ + 3 = 0&lt;br&gt;&lt;br&gt;
Factor: (λ - 1)(λ - 3) = 0&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Eigenvalues:&lt;/strong&gt; λ₁ = 1, λ₂ = 3&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Find eigenvectors&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For λ₁ = 1:&lt;br&gt;&lt;br&gt;
Solve (A - I)v = 0:&lt;br&gt;&lt;br&gt;
[[1, 1], [1, 1]] [v₁, v₂]ᵀ = 0 → v₁ + v₂ = 0&lt;br&gt;&lt;br&gt;
Choose v₁ = 1, then v₂ = -1&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Eigenvector:&lt;/strong&gt; v₁ = [1, -1]ᵀ&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For λ₂ = 3:&lt;br&gt;&lt;br&gt;
Solve (A - 3I)v = 0:&lt;br&gt;&lt;br&gt;
[[-1, 1], [1, -1]] [v₁, v₂]ᵀ = 0 → -v₁ + v₂ = 0&lt;br&gt;&lt;br&gt;
Choose v₁ = 1, then v₂ = 1&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Eigenvector:&lt;/strong&gt; v₂ = [1, 1]ᵀ&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verification:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A v₁ = [[2,1],[1,2]] [1, -1]ᵀ = [1, -1]ᵀ = 1 · v₁  
A v₂ = [[2,1],[1,2]] [1, 1]ᵀ = [3, 3]ᵀ = 3 · v₂
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why Does This Matter for Quantum Computing?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Quantum States Are Vectors
&lt;/h3&gt;

&lt;p&gt;A quantum system’s state (like an electron’s spin or a photon’s polarization) is represented by a vector in a complex vector space. For a single qubit, the state looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|ψ⟩ = α|0⟩ + β|1⟩
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;α&lt;/code&gt; and &lt;code&gt;β&lt;/code&gt; are complex numbers, and &lt;code&gt;|0⟩&lt;/code&gt;, &lt;code&gt;|1⟩&lt;/code&gt; are basis vectors.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Quantum Gates Are Matrices
&lt;/h3&gt;

&lt;p&gt;Quantum operations (gates like &lt;code&gt;X&lt;/code&gt;, &lt;code&gt;H&lt;/code&gt;, &lt;code&gt;CNOT&lt;/code&gt;) are unitary matrices. Applying a gate to a state means multiplying the state vector by that matrix.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Eigenvectors = Stable States
&lt;/h3&gt;

&lt;p&gt;When a quantum gate acts on one of its eigenvectors, the state only picks up a phase factor (a complex number of magnitude 1). In other words, the state’s “direction” in Hilbert space stays the same—it’s just rotated in phase. These eigenvectors are the &lt;strong&gt;invariant directions&lt;/strong&gt; under that gate.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Eigenvalues = Phase Shifts
&lt;/h3&gt;

&lt;p&gt;The eigenvalue (a complex number e&lt;sup&gt;iθ&lt;/sup&gt; for unitary gates) tells you how much phase the eigenstate acquires. Phase is crucial in quantum interference—the phenomenon that lets quantum algorithms amplify correct answers and cancel wrong ones.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Diagonalization = Simulating Quantum Evolution
&lt;/h3&gt;

&lt;p&gt;If you can find a basis of eigenvectors for a Hamiltonian (the energy operator governing time evolution), you can easily compute how the system evolves: each eigenstate just picks up a phase e&lt;sup&gt;-iEt/ℏ&lt;/sup&gt; where &lt;code&gt;E&lt;/code&gt; is the eigenvalue (energy). This is the foundation of algorithms like &lt;strong&gt;Quantum Phase Estimation&lt;/strong&gt; and &lt;strong&gt;Variational Quantum Eigensolver (VQE)&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Everyday Analogies
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eigenvector&lt;/strong&gt; = The “preferred spinning axis” of a quantum object under a certain operation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eigenvalue&lt;/strong&gt; = How much the object’s phase twists when spinning around that axis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quantum Algorithm&lt;/strong&gt; = Cleverly choosing operations so that the eigenvectors of the problem’s Hamiltonian align with the answer you want, then reading off the phases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Further Exploration (Lay‑Friendly)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/results?search_query=Quantum+Computing+for+the+Determined" rel="noopener noreferrer"&gt;Watch: “Quantum Computing for the Determined”&lt;/a&gt; – visual analogies of spin and phase.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.amazon.com/Quantum-Computing-since-Democritus-Aaronson/dp/0521199565" rel="noopener noreferrer"&gt;Read: “Quantum Computing Since Democritus” by Scott Aaronson&lt;/a&gt; – chapter on linear algebra, written with humor.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - &lt;a href="https://quantum-computing.ibm.com/" rel="noopener noreferrer"&gt;Experiment: Use the IBM Quantum Experience&lt;/a&gt; to prepare an eigenstate of a Pauli gate and see the phase kickback.
&lt;/h2&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>science</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding Reversible Quantum Computation: Why Reversibility Matters in Quantum Computing</title>
      <dc:creator>Malcolm Low</dc:creator>
      <pubDate>Fri, 24 Apr 2026 01:08:19 +0000</pubDate>
      <link>https://dev.to/malcolmlow/understanding-reversible-quantum-computation-why-reversibility-matters-in-quantum-computing-51id</link>
      <guid>https://dev.to/malcolmlow/understanding-reversible-quantum-computation-why-reversibility-matters-in-quantum-computing-51id</guid>
      <description>&lt;h1&gt;
  
  
  Understanding Reversible Quantum Computation: Why Reversibility Matters in Quantum Computing
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the pursuit of more efficient and powerful computing paradigms, reversible quantum computation stands at the intersection of fundamental physics and practical engineering. While classical computing has benefited enormously from reversible logic concepts, quantum computing inherently requires reversibility due to the unitary nature of quantum evolution. This article explores why reversibility is not just beneficial but essential in quantum computing, and how it shapes the design of quantum algorithms and hardware.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Thermodynamic Imperative: Landauer's Principle
&lt;/h2&gt;

&lt;p&gt;To understand why reversibility matters, we start with Rolf Landauer's groundbreaking insight from 1961: &lt;strong&gt;information erasure has a thermodynamic cost&lt;/strong&gt;. Specifically, erasing one bit of information necessarily dissipates at least kBT ln 2 joules of energy as heat, where k_B is Boltzmann's constant and T is the absolute temperature.&lt;/p&gt;

&lt;p&gt;This principle reveals a profound connection between information theory and thermodynamics. In conventional (irreversible) computing, logic gates like AND, OR, and NAND lose information about their inputs when producing outputs. For example, knowing the output of an AND gate doesn't tell you uniquely what the inputs were - multiple input combinations can produce the same output.&lt;/p&gt;

&lt;p&gt;Reversible computing avoids this information loss by ensuring that every computational step is invertible: given the output, you can uniquely determine the input. This eliminates the fundamental thermodynamic cost associated with information erasure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quantum Mechanics and Unitary Evolution
&lt;/h2&gt;

&lt;p&gt;In quantum computing, reversibility takes on even greater significance due to the postulates of quantum mechanics. The time evolution of a closed quantum system is described by the Schrödinger equation, which implies that quantum state transformations must be &lt;strong&gt;unitary&lt;/strong&gt; operations.&lt;/p&gt;

&lt;p&gt;A unitary operation U satisfies U&lt;sup&gt;†&lt;/sup&gt;U = I, where U† is the conjugate transpose of U and I is the identity matrix. This property guarantees that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The transformation is reversible (invertible)&lt;/li&gt;
&lt;li&gt;Probability is preserved (the norm of the state vector remains 1)&lt;/li&gt;
&lt;li&gt;No information is lost during the computation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every quantum gate must therefore be represented by a unitary matrix. This is why quantum circuits are composed of reversible gates - it's not an optimization choice, but a fundamental requirement imposed by quantum mechanics itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Essential Reversible Quantum Gates
&lt;/h2&gt;

&lt;p&gt;Several key gates form the foundation of reversible quantum computation:&lt;/p&gt;

&lt;h3&gt;
  
  
  The CNOT Gate (Controlled-NOT)
&lt;/h3&gt;

&lt;p&gt;The CNOT gate flips the target qubit if and only if the control qubit is |1⟩:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|00⟩ → |00⟩
|01⟩ → |01⟩
|10⟩ → |11⟩
|11⟩ → |10⟩
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its unitary matrix is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Toffoli Gate (CCNOT)
&lt;/h3&gt;

&lt;p&gt;Often called the "quantum AND gate," the Toffoli gate flips the target qubit only when both control qubits are |1⟩. It's universal for classical reversible computation and, when combined with Hadamard gates, becomes universal for quantum computation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fredkin Gate (CSWAP)
&lt;/h3&gt;

&lt;p&gt;This controlled-swap gate exchanges the states of two target qubits conditioned on a control qubit being |1⟩. Like the Toffoli, it's universal for reversible classical computation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single-Qubit Rotations
&lt;/h3&gt;

&lt;p&gt;Gates like the Hadamard (H), phase (S), and π/8 (T) gates, along with rotation gates (Rx, Ry, Rz), are all unitary and reversible. The Hadamard gate, for instance, is its own inverse: &lt;span&gt;H&lt;sup&gt;2&lt;/sup&gt; = I&lt;/span&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Reversibility Enables Quantum Advantage
&lt;/h2&gt;

&lt;p&gt;The requirement of reversibility in quantum computing isn't merely a constraint - it's what enables quantum advantage:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interference&lt;/strong&gt;: Reversible unitary operations preserve quantum coherence, allowing probability amplitudes to interfere constructively and destructively. This interference is the mechanism behind quantum speedups in algorithms like Grover's search and Shor's factoring.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Entanglement Generation&lt;/strong&gt;: Reversible gates like CNOT can create entangled states from separable ones. Entanglement, a uniquely quantum correlation, is essential for most quantum speedups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error Correction&lt;/strong&gt;: Quantum error correction codes rely on the ability to reversibly encode and decode logical qubits into entangled states of multiple physical qubits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Algorithmic Structure&lt;/strong&gt;: Many quantum algorithms (e.g., quantum Fourier transform, amplitude amplification) are built from sequences of reversible operations that manipulate interference patterns to increase the probability of correct answers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Reversibility vs. Irreversibility in Quantum Measurement
&lt;/h2&gt;

&lt;p&gt;It's important to distinguish between quantum gate operations (which must be reversible) and quantum measurement (which is inherently irreversible). Measurement collapses the quantum state according to the Born rule, losing information about the pre-measurement superposition.&lt;/p&gt;

&lt;p&gt;This asymmetry is fundamental: while quantum evolution is unitary and reversible, measurement introduces irreversibility and thermodynamical cost. Quantum algorithms carefully separate these phases - performing many reversible operations to shape the probability distribution, then performing a (typically) single irreversible measurement to extract the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Implications for Quantum Hardware
&lt;/h2&gt;

&lt;p&gt;The reversibility constraint affects quantum hardware design in several ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  Gate Design
&lt;/h3&gt;

&lt;p&gt;Physical implementations of quantum gates must realize unitary operations. This requires precise control over quantum systems (trapped ions, superconducting circuits, photonic systems, etc.) to implement the desired unitary without introducing dissipation or decoherence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error Sources
&lt;/h3&gt;

&lt;p&gt;Irreversible processes in quantum hardware (decoherence, relaxation, dephasing) represent deviations from ideal unitary evolution. Quantum error correction aims to protect against these irreversibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Energy Considerations
&lt;/h3&gt;

&lt;p&gt;While Landauer's principle sets a lower bound on energy dissipation for irreversible classical operations, quantum gates ideally operate below this threshold since they're reversible. However, practical implementations still face energy costs from control electronics, cooling, and other overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applications and Current Research
&lt;/h2&gt;

&lt;p&gt;Reversible quantum computation finds applications across the quantum computing stack:&lt;/p&gt;

&lt;h3&gt;
  
  
  Algorithm Design
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shor's algorithm&lt;/strong&gt;: Relies on the quantum Fourier transform (a sequence of reversible gates) for period finding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grover's algorithm&lt;/strong&gt;: Uses reversible oracle and diffusion operators for amplitude amplification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quantum simulation&lt;/strong&gt;: Employs reversible Trotter-Suzuki decompositions to simulate Hamiltonian evolution&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quantum Error Correction
&lt;/h3&gt;

&lt;p&gt;Codes like the surface code use stabilizer measurements (which are effectively reversible when conditioned on measurement outcomes) to detect and correct errors without destroying the encoded quantum information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reversible Logic Synthesis
&lt;/h3&gt;

&lt;p&gt;Research continues on optimizing quantum circuits for minimal gate count, depth, and other metrics while preserving reversibility. Techniques include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Template matching and optimization&lt;/li&gt;
&lt;li&gt;Quantum circuit rewriting using algebraic identities&lt;/li&gt;
&lt;li&gt;Reversible pebble games for space-time tradeoffs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Reversible quantum computation is not merely an interesting theoretical corner - it's the very foundation upon which quantum computing rests. The requirement of unitary, reversible operations emerges directly from the postulates of quantum mechanics and enables the uniquely quantum phenomena of superposition, entanglement, and interference that give quantum computers their potential power.&lt;/p&gt;

&lt;p&gt;Understanding reversibility helps us appreciate why quantum computers look so different from classical ones, why quantum error correction is both necessary and possible, and how quantum algorithms achieve their remarkable feats of computation. As we continue to build larger and more reliable quantum computers, the principles of reversible computation will remain central to both theoretical advances and practical engineering breakthroughs.&lt;/p&gt;

&lt;p&gt;The next time you encounter a quantum circuit diagram, remember: each gate represents a reversible, unitary transformation - a carefully choreographed dance of quantum states that preserves information while shaping the probabilities that ultimately yield quantum advantage.&lt;/p&gt;




&lt;p&gt;*Tags: quantum-computing, reversible-computing, quantum-algorithms, quantum-physics&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>computerscience</category>
      <category>science</category>
    </item>
  </channel>
</rss>
