<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Notes</title>
<link>https://notes.zakacat.ca/</link>
<atom:link href="https://notes.zakacat.ca/index.xml" rel="self" type="application/rss+xml"/>
<description>Technical notes on various topics of interest — data, quantum computing, and software engineering, by Zak Toews.</description>
<image>
<url>https://notes.zakacat.ca/og-image.png</url>
<title>Notes</title>
<link>https://notes.zakacat.ca/</link>
<height>76</height>
<width>144</width>
</image>
<generator>quarto-1.4.554</generator>
<lastBuildDate>Sat, 20 Jun 2026 00:00:00 GMT</lastBuildDate>
<item>
  <title>Data: Main Site</title>
  <dc:creator>Zak Toews</dc:creator>
  <link>https://notes.zakacat.ca/notebooks/MainSiteData.html</link>
  <description><![CDATA[ 




<center>
<section id="data-main-site" class="level1">
<h1><strong>Data: Main Site</strong></h1>
<section id="by-zak-toews-with-assistance-of-ai" class="level3">
<h3 class="anchored" data-anchor-id="by-zak-toews-with-assistance-of-ai">By Zak Toews with assistance of AI</h3>
</section>
<section id="th-year-software-engineering-student-and-hobbyist" class="level3">
<h3 class="anchored" data-anchor-id="th-year-software-engineering-student-and-hobbyist">4th Year Software Engineering Student and Hobbyist</h3>
</section></section></center>


<section id="table-of-contents" class="level1">
<h1>Table of Contents</h1>
<ol type="1">
<li>Data Collected</li>
<li>Notes about Data</li>
<li>Tools and Techniques</li>
<li>Importing the Data</li>
<li>Visualizing the Data</li>
<li>Classifying Contact Interest</li>
<li>Clustering Sessions into Behavioral Groups</li>
<li>Association Analysis: What Site Behaviors Go Together</li>
</ol>
<section id="data-collected" class="level2">
<h2 class="anchored" data-anchor-id="data-collected">Data Collected</h2>
<p>All data is anonymous. No personal data is recorded.</p>
<p>This is subject to change as the analytics evolve.</p>
<section id="analytics-event-table" class="level3">
<h3 class="anchored" data-anchor-id="analytics-event-table">Analytics Event Table</h3>
<p><strong>id</strong> (string) - Event specific ID</p>
<p><strong>event</strong> (enum)- Different types of events and their corresponding properties<br>
- <strong>page_load</strong> - Triggered on page load<br>
- <strong>section_viewed</strong> (enum)- Sections viewed include “about”, “experience”, “research”, “contact”<br>
- <strong>scroll_depth</strong> (enum)- As percentage of the total length of the main page - 25, 50, 75, 100<br>
- <strong>link_clicked</strong> (enum)- This event is fired anytime a user clicks a link - “planner”, “notes”, “old-site”, “email”, “ayuda”, “youtube”<br>
- <strong>nav_clicked</strong> (enum) - This event is fired when a user navgiates to sections using the nav links at the top of the site - “about”, “experience”, “research”, “contact”</p>
<p><strong>sessionId</strong> (string) - Randomly generated ID for browser session</p>
<p><strong>createdAt</strong> (time) - A precise time stamp</p>
<p><strong>service</strong> (enum) - We will only be concerned with “main-site” for now</p>
</section>
<section id="feedback-table" class="level3">
<h3 class="anchored" data-anchor-id="feedback-table">Feedback Table</h3>
<p><strong>id</strong> (string) - Feedback specific ID</p>
<p><strong>category</strong> (enum) - The feedback category selected by the user - “Suggestion”, “Bug Report”, “Other”</p>
<p><strong>message</strong> (string) - Max of 500 characters to explain feedback</p>
<p><strong>contact</strong> (string) - Just a string, any information could be put into here</p>
<p><strong>service</strong> (string) - Currently always “main-site”</p>
<p><strong>createdAt</strong> (time) - A precise time stamp</p>
</section>
</section>
<section id="notes-about-data" class="level2">
<h2 class="anchored" data-anchor-id="notes-about-data">Notes about Data</h2>
<p>The <code>AnalyticsEvent</code> table has two different <code>id</code>/<code>createdAt</code> formats mixed together:</p>
<ul>
<li><strong>main-site</strong> events (raw SQL insert) always used <code>gen_random_uuid()</code> for <code>id</code> and Postgres’s <code>NOW()</code> for <code>createdAt</code> — a UUID and microsecond-precision timestamp.</li>
<li><strong>trip-planner</strong> events (via Prisma) used Prisma’s client-side <code>cuid()</code> and <code>Date.now()</code> defaults instead of the database — a cuid and only millisecond-precision timestamp.</li>
</ul>
<p>This got fixed at the schema level (<code>trip-planner/prisma/schema.prisma</code> now uses <code>dbgenerated("gen_random_uuid()")</code> / <code>dbgenerated("now()")</code> for both fields, so <em>new</em> trip-planner rows match main-site’s format exactly). But a schema default only changes future inserts — rows written before the fix keep their original cuid/millisecond format forever. So any notebook reading this table needs to tolerate both formats existing side by side in the same column.</p>
</section>
<section id="tools-and-techniques" class="level2">
<h2 class="anchored" data-anchor-id="tools-and-techniques">Tools and Techniques</h2>
<p>Everything below builds on a small set of Python libraries and a handful of core data-mining concepts. This section is a quick reference for what each one does and why it’s useful - skip ahead if you’re already familiar, or come back here whenever a technique further down feels unfamiliar.</p>
<section id="core-libraries" class="level3">
<h3 class="anchored" data-anchor-id="core-libraries">Core libraries</h3>
<table class="table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Library</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>pandas</strong></td>
<td>Loads, filters, groups, and reshapes tabular data (<code>DataFrame</code>s). Nearly every cell below starts by transforming raw event rows into a per-session table.</td>
</tr>
<tr class="even">
<td><strong>matplotlib</strong></td>
<td>Draws every chart in this notebook - box plots, scatter matrices, dendrograms, ROC curves.</td>
</tr>
<tr class="odd">
<td><strong>scikit-learn</strong></td>
<td>Supplies the classifiers, clustering algorithms, evaluation metrics, and hyperparameter search tools used throughout.</td>
</tr>
<tr class="even">
<td><strong>scipy</strong></td>
<td>Used once, for hierarchical clustering’s dendrogram.</td>
</tr>
</tbody>
</table>
</section>
<section id="why-turn-raw-events-into-a-session-table" class="level3">
<h3 class="anchored" data-anchor-id="why-turn-raw-events-into-a-session-table">Why turn raw events into a “session table”?</h3>
<p>Data-mining algorithms expect <strong>one row per observation, one column per feature</strong> - a shape pandas calls “tidy.” The raw <code>AnalyticsEvent</code> table is one row per <em>event</em> (a single session might have 20 rows). The <code>session_metrics</code> table built in Classifying Contact Interest collapses that down to one row per <em>session</em>, with engineered columns like <code>total_actions</code> and <code>max_scroll_depth</code>. That reshaping step is what makes every classifier, clustering algorithm, and association-rule search below possible.</p>
</section>
<section id="supervised-learning-classifiers" class="level3">
<h3 class="anchored" data-anchor-id="supervised-learning-classifiers">Supervised learning: classifiers</h3>
<p>These all answer the same question - “given a session’s features, predict whether it shows <code>contact_interest</code>” - using different strategies:</p>
<table class="table">
<colgroup>
<col style="width: 33%">
<col style="width: 33%">
<col style="width: 33%">
</colgroup>
<thead>
<tr class="header">
<th>Classifier</th>
<th>How it decides</th>
<th>Why it’s here</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>Decision Tree</strong></td>
<td>Asks a sequence of yes/no questions about one feature at a time.</td>
<td>Easy to read and explain - the whole “reasoning” can be printed as text or drawn as a diagram.</td>
</tr>
<tr class="even">
<td><strong>K-Nearest Neighbors (KNN)</strong></td>
<td>Looks at the <em>k</em> most similar past sessions and votes.</td>
<td>No training step, and very sensitive to feature scale - a good teaching example for <em>why</em> scaling matters.</td>
</tr>
<tr class="odd">
<td><strong>Random Forest</strong></td>
<td>Averages many decision trees, each trained on a random subset of the data.</td>
<td>Usually more accurate and more resistant to overfitting than a single tree.</td>
</tr>
<tr class="even">
<td><strong>Bagging</strong></td>
<td>The same “average many models” idea as Random Forest, but with a base model you choose yourself.</td>
<td>Shows that <em>ensembling</em> is a separate idea from <em>decision trees</em> specifically - it works with any base classifier.</td>
</tr>
<tr class="odd">
<td><strong>Gaussian Naive Bayes</strong></td>
<td>Assumes each feature is normally distributed within a class, and combines their probabilities.</td>
<td>Extremely fast with no hyperparameters to tune - a useful “does anything more complex actually help?” comparison point.</td>
</tr>
<tr class="even">
<td><strong>Dummy (baseline)</strong></td>
<td>Always predicts the majority class, ignoring the features entirely.</td>
<td>The floor every real classifier has to beat. If a “real” classifier can’t outperform this, it isn’t learning anything from the data.</td>
</tr>
</tbody>
</table>
</section>
<section id="evaluating-a-classifier" class="level3">
<h3 class="anchored" data-anchor-id="evaluating-a-classifier">Evaluating a classifier</h3>
<p>A single accuracy number can be misleading, especially once one class is rarer than the other:</p>
<table class="table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Metric / technique</th>
<th>What it tells you</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>Accuracy</strong></td>
<td>Percent of predictions that were correct. Misleading on unbalanced data - a classifier that always guesses the majority class can still score high.</td>
</tr>
<tr class="even">
<td><strong>Confusion matrix</strong></td>
<td>Breaks predictions into true/false positives and negatives, so you can see <em>what kind</em> of mistake a classifier makes.</td>
</tr>
<tr class="odd">
<td><strong>Precision</strong></td>
<td>Of the sessions predicted <code>contact_interest</code>, how many actually were? High precision means few false alarms.</td>
</tr>
<tr class="even">
<td><strong>Recall</strong></td>
<td>Of the sessions that actually were <code>contact_interest</code>, how many did the classifier catch? High recall means few missed cases.</td>
</tr>
<tr class="odd">
<td><strong>F1 score</strong></td>
<td>A single number balancing precision and recall.</td>
</tr>
<tr class="even">
<td><strong>ROC curve</strong></td>
<td>Plots true-positive rate against false-positive rate across every possible decision threshold - a way to compare classifiers independent of any one threshold choice.</td>
</tr>
<tr class="odd">
<td><strong>Train/test split</strong></td>
<td>Trains on part of the data, tests on data the model never saw, so the resulting accuracy reflects generalization rather than memorization.</td>
</tr>
<tr class="even">
<td><strong>k-fold cross-validation</strong></td>
<td>Repeats the train/test split <em>k</em> times with different slices, giving a distribution of scores instead of one number that depends on how a single split happened to land.</td>
</tr>
</tbody>
</table>
</section>
<section id="feature-engineering-and-hyperparameter-search" class="level3">
<h3 class="anchored" data-anchor-id="feature-engineering-and-hyperparameter-search">Feature engineering and hyperparameter search</h3>
<table class="table">
<colgroup>
<col style="width: 33%">
<col style="width: 33%">
<col style="width: 33%">
</colgroup>
<thead>
<tr class="header">
<th>Technique</th>
<th>What it does</th>
<th>Why it matters</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>Feature scaling</strong> (<code>StandardScaler</code>)</td>
<td>Rescales every feature to a comparable range.</td>
<td>Distance-based methods (KNN, clustering) would otherwise let whichever feature has the largest raw numbers dominate.</td>
</tr>
<tr class="even">
<td><strong>GridSearchCV</strong></td>
<td>Systematically tries every combination in a set of hyperparameters and cross-validates each one.</td>
<td>Replaces manual trial-and-error with an exhaustive, repeatable search.</td>
</tr>
</tbody>
</table>
</section>
<section id="unsupervised-learning-finding-structure-without-labels" class="level3">
<h3 class="anchored" data-anchor-id="unsupervised-learning-finding-structure-without-labels">Unsupervised learning: finding structure without labels</h3>
<p>Unlike the classifiers above, these don’t use <code>contact_interest</code> at all - they look for structure in the session features alone:</p>
<table class="table">
<thead>
<tr class="header">
<th>Technique</th>
<th>What it finds</th>
<th>Why it’s here</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>K-means</strong></td>
<td>Splits sessions into <em>k</em> groups, each centered on a mean point.</td>
<td>Formalizes the “user persona” idea from Visualizing the Data - do sessions naturally fall into a few behavioral types?</td>
</tr>
<tr class="even">
<td><strong>Hierarchical clustering / dendrogram</strong></td>
<td>Builds a tree of nested groupings, from every session as its own cluster up to one big cluster.</td>
<td>Doesn’t require picking <em>k</em> in advance, and the dendrogram is genuinely readable at this dataset’s small size.</td>
</tr>
<tr class="odd">
<td><strong>DBSCAN</strong></td>
<td>Groups points that are densely packed together, and labels sparse points as noise.</td>
<td>A different definition of “cluster” - density-based instead of distance-to-center-based.</td>
</tr>
<tr class="even">
<td><strong>Anomaly detection</strong> (Robust Covariance, One-Class SVM, Local Outlier Factor)</td>
<td>Flags the sessions that look least like the rest.</td>
<td>Useful for catching bot traffic or unusually extreme sessions, not for finding groups.</td>
</tr>
</tbody>
</table>
</section>
<section id="association-analysis" class="level3">
<h3 class="anchored" data-anchor-id="association-analysis">Association analysis</h3>
<p><strong>Frequent itemsets</strong> and <strong>association rules</strong> answer a different kind of question entirely - not “predict a label” or “find groups,” but “which behaviors tend to occur together?” (e.g.&nbsp;“sessions that scroll to 100% also tend to click Contact”). See Association Analysis for how this gets adapted to session data.</p>
</section>
</section>
<section id="importing-the-data" class="level2">
<h2 class="anchored" data-anchor-id="importing-the-data">Importing the Data</h2>
<p>We load the raw <code>AnalyticsEvent</code> export, normalize the two timestamp/id formats described above into one consistent shape, then narrow down to <code>main-site</code> events only and treat <code>event</code> as a categorical column so the rest of the notebook can group and count by event type cleanly.</p>
<div id="6f5d6cec-6e9f-4e15-9c64-55fee845a5c5" class="cell" data-execution_count="1">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>matplotlib inline</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> json</span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb1-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> numpy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> np</span>
<span id="cb1-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb1-8"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.cluster <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> KMeans</span>
<span id="cb1-9"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.decomposition <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> PCA</span>
<span id="cb1-10"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.preprocessing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> StandardScaler</span>
<span id="cb1-11"></span>
<span id="cb1-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Read the csv as a Pandas table</span></span>
<span id="cb1-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (the data-dump pipeline writes CSVs under notes/notebooks/data/ - see CLAUDE.md -</span></span>
<span id="cb1-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># shared by both draft and published notebooks)</span></span>
<span id="cb1-15">events <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data/analytics_event.csv"</span>)</span>
<span id="cb1-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Show the table as it is read in</span></span>
<span id="cb1-17">events</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="1">
<div>
<div>


<table class="dataframe table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">id</th>
<th data-quarto-table-cell-role="th">event</th>
<th data-quarto-table-cell-role="th">properties</th>
<th data-quarto-table-cell-role="th">sessionId</th>
<th data-quarto-table-cell-role="th">createdAt</th>
<th data-quarto-table-cell-role="th">service</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>cmqqq040x001jqgjo2poi6ym1</td>
<td>page_load</td>
<td>{}</td>
<td>miki8egczbrmqqq03qr</td>
<td>2026-06-23 07:09:06.603-07</td>
<td>trip-planner</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>cmqqqskt2001kqgjoq3j1u21j</td>
<td>page_load</td>
<td>{}</td>
<td>fvr6awmbhy5mqqqsjvo</td>
<td>2026-06-23 07:31:14.717-07</td>
<td>trip-planner</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2</td>
<td>cmqqqtror001lqgjoajbjzrhv</td>
<td>page_load</td>
<td>{}</td>
<td>z9a2kc0k9simqqqtr9a</td>
<td>2026-06-23 07:32:10.346-07</td>
<td>trip-planner</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">3</td>
<td>cmqqs41zx001mqgjox4soj63v</td>
<td>page_load</td>
<td>{}</td>
<td>d4tpym359nvmqqs41w3</td>
<td>2026-06-23 08:08:09.772-07</td>
<td>trip-planner</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">4</td>
<td>4e55128c-2284-49a9-b8cb-7104c20870c2</td>
<td>page_load</td>
<td>{}</td>
<td>ayv6yrctjgmqqzlb90</td>
<td>2026-06-23 11:37:34.118451-07</td>
<td>main-site</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2311</td>
<td>bc71c7fb-fb65-4d59-8eaa-958eac3af04d</td>
<td>page_load</td>
<td>{"tool": "home"}</td>
<td>k8x5wxubokmv09x2gk</td>
<td>2026-10-08 18:15:22.058101-07</td>
<td>quantum</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">2312</td>
<td>fe1096ff-64f4-448a-a9f9-54c01997a8f4</td>
<td>page_load</td>
<td>{"page": "atlas"}</td>
<td>61bzmctmth6mv0l8r1b</td>
<td>2026-10-08 23:32:22.80349-07</td>
<td>main-site</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2313</td>
<td>7d91ac70-5390-4eda-b390-ea234472af24</td>
<td>page_load</td>
<td>{"tool": "home"}</td>
<td>kfq998r41fmv0ys12b</td>
<td>2026-10-09 05:51:17.327784-07</td>
<td>quantum</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">2314</td>
<td>fe6b861b-943d-4d0a-a0d8-2b1638129e80</td>
<td>page_load</td>
<td>{"tool": "home"}</td>
<td>37opms02katmv10jydf</td>
<td>2026-10-09 06:40:59.832985-07</td>
<td>quantum</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2315</td>
<td>e5eabde4-42fc-4d15-9680-c18625017dca</td>
<td>page_load</td>
<td>{}</td>
<td>qmyd3h1ee28mv12j59u</td>
<td>2026-10-09 07:36:21.316821-07</td>
<td>sky</td>
</tr>
</tbody>
</table>

<p>2316 rows × 6 columns</p>
</div>
</div>
</div>
</div>
<div id="e24f3353-1c86-41b6-b985-14a918c56cfc" class="cell" data-execution_count="2">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Normalize the different time formats to meet  ISO8601</span></span>
<span id="cb2-2">events[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"createdAt"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.to_datetime(events[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"createdAt"</span>], <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">format</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ISO8601"</span>, utc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb2-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># parse the json properties</span></span>
<span id="cb2-4">events[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"properties"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> events[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"properties"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(json.loads)</span>
<span id="cb2-5"></span>
<span id="cb2-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Print the total amounts of events an service</span></span>
<span id="cb2-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(events)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> events, </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>events[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'service'</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>nunique()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> services"</span>)</span>
<span id="cb2-8"></span>
<span id="cb2-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># show the amounts of each type of service... We are only concerned with mainsite</span></span>
<span id="cb2-10">events[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"service"</span>].value_counts()</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>2316 events, 5 services</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>service
main-site       1178
trip-planner     476
quantum          246
sky              232
notes            184
Name: count, dtype: int64</code></pre>
</div>
</div>
<div id="9bf077f6-e7c6-41dd-9e9b-1dc40e582178" class="cell" data-execution_count="3">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Confirm both id/timestamp eras are actually present, and that parsing didn't drop anything.</span></span>
<span id="cb5-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Not every render has both eras - a fresh/sparse local dev database may only have one</span></span>
<span id="cb5-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (or neither), so this reports what's actually present instead of assuming a full</span></span>
<span id="cb5-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># production-shaped history.</span></span>
<span id="cb5-5">old_era <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> events[events[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>.startswith(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cm"</span>)]   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># trip-planner cuid era</span></span>
<span id="cb5-6">new_era <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> events[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>events[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>.startswith(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cm"</span>)]  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># gen_random_uuid era</span></span>
<span id="cb5-7"></span>
<span id="cb5-8"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(old_era) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb5-9">    sample_old <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> old_era.iloc[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb5-10">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuid era     :"</span>, sample_old[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id"</span>], sample_old[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"createdAt"</span>])</span>
<span id="cb5-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb5-12">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cuid era     : none present in this dataset"</span>)</span>
<span id="cb5-13"></span>
<span id="cb5-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(new_era) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb5-15">    sample_new <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> new_era.iloc[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb5-16">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"uuid/NOW era :"</span>, sample_new[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id"</span>], sample_new[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"createdAt"</span>])</span>
<span id="cb5-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb5-18">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"uuid/NOW era : none present in this dataset"</span>)</span>
<span id="cb5-19"></span>
<span id="cb5-20"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">assert</span> events[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"createdAt"</span>].isna().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"some timestamps failed to parse"</span></span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>cuid era     : cmqqq040x001jqgjo2poi6ym1 2026-06-23 14:09:06.603000+00:00
uuid/NOW era : 4e55128c-2284-49a9-b8cb-7104c20870c2 2026-06-23 18:37:34.118451+00:00</code></pre>
</div>
</div>
<div id="9bc1520f-18f0-4ca3-85c5-fdd2a03c19f1" class="cell" data-execution_count="4">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Now we can strip out the trip planner data</span></span>
<span id="cb7-2">main_site <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> events[events[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"service"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"main-site"</span>].copy()</span>
<span id="cb7-3"></span>
<span id="cb7-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Show the top 5 results from the table</span></span>
<span id="cb7-5">main_site.head()</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="4">
<div>
<div>


<table class="dataframe table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">id</th>
<th data-quarto-table-cell-role="th">event</th>
<th data-quarto-table-cell-role="th">properties</th>
<th data-quarto-table-cell-role="th">sessionId</th>
<th data-quarto-table-cell-role="th">createdAt</th>
<th data-quarto-table-cell-role="th">service</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">4</td>
<td>4e55128c-2284-49a9-b8cb-7104c20870c2</td>
<td>page_load</td>
<td>{}</td>
<td>ayv6yrctjgmqqzlb90</td>
<td>2026-06-23 18:37:34.118451+00:00</td>
<td>main-site</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">7</td>
<td>94f66e36-2ce1-4392-a213-828fa36ae170</td>
<td>page_load</td>
<td>{}</td>
<td>nj17pvtvly9mqr3jd1j</td>
<td>2026-06-23 20:28:00.434174+00:00</td>
<td>main-site</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">17</td>
<td>81e9c854-83db-4f14-b360-6413b4ef530f</td>
<td>page_load</td>
<td>{}</td>
<td>slx8anuwuremqrbc4do</td>
<td>2026-06-24 00:06:19.830965+00:00</td>
<td>main-site</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">18</td>
<td>220eb49f-c8d6-463e-b087-bc33ed2273cc</td>
<td>page_load</td>
<td>{}</td>
<td>9ewxvfuudiamqrcx5vv</td>
<td>2026-06-24 00:50:40.628926+00:00</td>
<td>main-site</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">19</td>
<td>7e505a28-f0ab-4459-941b-576546fd77ed</td>
<td>page_load</td>
<td>{}</td>
<td>q25txt5b7zmqre5eto</td>
<td>2026-06-24 01:25:05.179063+00:00</td>
<td>main-site</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</div>
<div id="156cfefe-3622-483e-81cc-67d42f647858" class="cell" data-execution_count="5">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># confirm column data types</span></span>
<span id="cb8-2">main_site.dtypes</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>id                            str
event                         str
properties                 object
sessionId                     str
createdAt     datetime64[us, UTC]
service                       str
dtype: object</code></pre>
</div>
</div>
<div id="89fab3d1-0524-4e46-9285-a7bbb91bbc8b" class="cell" data-execution_count="6">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># change event type to categorical to associate an integer with the names</span></span>
<span id="cb10-2">main_site.event <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> main_site.event.astype(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'category'</span>)</span></code></pre></div>
</details>
</div>
<div id="373617ee-35e6-4d8b-9254-b79e99afd69f" class="cell" data-execution_count="7">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">main_site.dtypes</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>id                            str
event                    category
properties                 object
sessionId                     str
createdAt     datetime64[us, UTC]
service                       str
dtype: object</code></pre>
</div>
</div>
</section>
<section id="visualizing-the-data" class="level2">
<h2 class="anchored" data-anchor-id="visualizing-the-data">Visualizing the Data</h2>
<p>A first look at how people actually use the site: how long sessions last, how many actions they trigger, and how far they scroll - each shown as a box-and-whisker plot with the underlying numbers spelled out in prose below it.</p>
<div id="62af0502-99a3-4350-9c51-06792d92000b" class="cell" data-execution_count="8">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Find the start and end time for each session</span></span>
<span id="cb13-2">session_times <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> main_site.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>)[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'createdAt'</span>].agg([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'min'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>])</span>
<span id="cb13-3"></span>
<span id="cb13-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Calculate duration in minutes</span></span>
<span id="cb13-5">session_times[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (session_times[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> session_times[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'min'</span>]).dt.total_seconds() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">60.0</span></span>
<span id="cb13-6"></span>
<span id="cb13-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 3. Cap duration for these visualizations only - a single session with an idle open</span></span>
<span id="cb13-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># tab can run for hours and swamps the scale of a box plot / scatter matrix. 100</span></span>
<span id="cb13-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># minutes is a generous cap for someone actually reading the site. This only affects</span></span>
<span id="cb13-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the charts below - the classifier later in this notebook still trains on the real,</span></span>
<span id="cb13-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># uncapped duration.</span></span>
<span id="cb13-12">DURATION_CAP_MINUTES <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="cb13-13">session_times[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session_times[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>].clip(upper<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>DURATION_CAP_MINUTES)</span>
<span id="cb13-14"></span>
<span id="cb13-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 4. Create the boxplot</span></span>
<span id="cb13-16">session_times.boxplot(column<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-9-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p><strong>Reading the box plot:</strong> the box spans the 1st to 3rd quartile, the green line marks the median, and the whiskers show the normal range of the data - circled points beyond them are outliers. Duration here is capped at 100 minutes (see the code above) so a rare session where someone left the tab open for hours doesn’t flatten the whole chart.</p>
<div id="913aee8d-8c94-4ca0-b7c9-85b98d5349ad" class="cell" data-execution_count="9">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Calculate the components dynamically</span></span>
<span id="cb14-2">stats <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session_times[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>].describe()</span>
<span id="cb14-3"></span>
<span id="cb14-4">median_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'50%'</span>]</span>
<span id="cb14-5">q1_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'25%'</span>]</span>
<span id="cb14-6">q3_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'75%'</span>]</span>
<span id="cb14-7">max_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>]</span>
<span id="cb14-8"></span>
<span id="cb14-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Format the dynamic print statement</span></span>
<span id="cb14-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(</span>
<span id="cb14-11">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Therefore, we can conclude that a typical user session duration is </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>median_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> minutes (the median).</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb14-12">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"The middle 50% of our users stay between </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>q1_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> and </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>q3_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> minutes (the box range).</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb14-13">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"The chart above caps duration at </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>DURATION_CAP_MINUTES<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> minutes, so the </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>max_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> minute maximum shown</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb14-14">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"here is the capped value, not the true longest session - a handful of real sessions run far longer</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb14-15">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"than that (people who leave the tab open), which is exactly why the cap exists.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb14-16">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"We most also take into consideration that the duration is calculated by the first and last event per session.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb14-17">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"This means that a user could stay on the page for some time after without triggering another event."</span></span>
<span id="cb14-18">)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Therefore, we can conclude that a typical user session duration is 0.00 minutes (the median).
The middle 50% of our users stay between 0.00 and 0.02 minutes (the box range).
The chart above caps duration at 100 minutes, so the 100.00 minute maximum shown
here is the capped value, not the true longest session - a handful of real sessions run far longer
than that (people who leave the tab open), which is exactly why the cap exists.

We most also take into consideration that the duration is calculated by the first and last event per session.
This means that a user could stay on the page for some time after without triggering another event.</code></pre>
</div>
</div>
<div id="1d38c8d0-7c92-41c5-be24-ef6fec787ee9" class="cell" data-execution_count="10">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Count how many events happen in each session</span></span>
<span id="cb16-2">session_counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> main_site.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>).size().reset_index(name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'event_count'</span>)</span>
<span id="cb16-3"></span>
<span id="cb16-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Boxplot the distribution of activity</span></span>
<span id="cb16-5">session_counts.boxplot(column<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'event_count'</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-11-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="926c1fe4-03cf-4266-a858-844f5ed9113b" class="cell" data-execution_count="11">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Calculate the components dynamically</span></span>
<span id="cb17-2">stats <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session_counts[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'event_count'</span>].describe()</span>
<span id="cb17-3"></span>
<span id="cb17-4">median_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'50%'</span>]</span>
<span id="cb17-5">q1_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'25%'</span>]</span>
<span id="cb17-6">q3_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'75%'</span>]</span>
<span id="cb17-7">max_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>]</span>
<span id="cb17-8"></span>
<span id="cb17-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Format the dynamic print statement</span></span>
<span id="cb17-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(</span>
<span id="cb17-11">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Therefore, we can conclude that a typical user session consists of </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>median_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> events (the median).</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb17-12">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"The middle 50% of our users trigger between </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>q1_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> and </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>q3_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> events (the box range).</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb17-13">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"While the absolute maximum recorded activity was </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>max_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> events, the whiskers show the normal</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb17-14">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"range of data, meaning extreme high values are likely just click-happy users."</span></span>
<span id="cb17-15">)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Therefore, we can conclude that a typical user session consists of 1.00 events (the median).
The middle 50% of our users trigger between 1.00 and 2.00 events (the box range).
While the absolute maximum recorded activity was 19.00 events, the whiskers show the normal
range of data, meaning extreme high values are likely just click-happy users.</code></pre>
</div>
</div>
<div id="0fd8b875-fff4-46e2-af31-7e4e2a60af35" class="cell" data-execution_count="12">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Filter for scroll events</span></span>
<span id="cb19-2">scroll_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> main_site[main_site[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'event'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'scroll_depth'</span>].copy()</span>
<span id="cb19-3"></span>
<span id="cb19-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Extract the number from the JSON string safely</span></span>
<span id="cb19-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">def</span> extract_percent(prop_str):</span>
<span id="cb19-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">try</span>:</span>
<span id="cb19-7">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># If it's already a dict, grab it; if it's a string, parse it as JSON</span></span>
<span id="cb19-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(prop_str, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>):</span>
<span id="cb19-9">            <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">return</span> prop_str.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'percent'</span>)</span>
<span id="cb19-10">        </span>
<span id="cb19-11">        data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> json.loads(prop_str)</span>
<span id="cb19-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">return</span> data.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'percent'</span>)</span>
<span id="cb19-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">except</span> (json.JSONDecodeError, <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">TypeError</span>, <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">AttributeError</span>):</span>
<span id="cb19-14">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb19-15"></span>
<span id="cb19-16">scroll_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'depth'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> scroll_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'properties'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(extract_percent)</span>
<span id="cb19-17"></span>
<span id="cb19-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 3. Ensure it is numeric</span></span>
<span id="cb19-19">scroll_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'depth'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.to_numeric(scroll_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'depth'</span>], errors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'coerce'</span>)</span>
<span id="cb19-20"></span>
<span id="cb19-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 4. Create the plot! </span></span>
<span id="cb19-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (We drop 'by=sessionId' here to avoid the ugly X-axis problem)</span></span>
<span id="cb19-23">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb19-24">scroll_data.boxplot(column<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'depth'</span>)</span>
<span id="cb19-25"></span>
<span id="cb19-26">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Overall User Scroll Depth Distribution"</span>)</span>
<span id="cb19-27">plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scroll Percentage (%)"</span>)</span>
<span id="cb19-28">plt.show()</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-13-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="5b769e88-8111-45ce-9413-8d479fea9556" class="cell" data-execution_count="13">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Calculate the components dynamically</span></span>
<span id="cb20-2">stats <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> scroll_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'depth'</span>].describe()</span>
<span id="cb20-3"></span>
<span id="cb20-4">median_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'50%'</span>]</span>
<span id="cb20-5">q1_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'25%'</span>]</span>
<span id="cb20-6">q3_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'75%'</span>]</span>
<span id="cb20-7">max_val <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>]</span>
<span id="cb20-8"></span>
<span id="cb20-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Format the dynamic print statement</span></span>
<span id="cb20-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(</span>
<span id="cb20-11">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Therefore, we can conclude that a typical user scrolls to </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>median_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.1f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> % (the median) of the main page.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb20-12">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"The middle 50% of our users scroll between </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>q1_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.1f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> and </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>q3_val<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.1f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> events (the box range)."</span></span>
<span id="cb20-13">)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Therefore, we can conclude that a typical user scrolls to 50.0 % (the median) of the main page.
The middle 50% of our users scroll between 25.0 and 75.0 events (the box range).</code></pre>
</div>
</div>
<div id="52b28956-dcbd-4798-b4c0-3ccadaa5b014" class="cell" data-execution_count="14">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Create a clean metrics DataFrame per session</span></span>
<span id="cb22-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Total events per session</span></span>
<span id="cb22-3">session_metrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> main_site.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>).size().reset_index(name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'total_actions'</span>)</span>
<span id="cb22-4"></span>
<span id="cb22-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Session duration in minutes</span></span>
<span id="cb22-6">times <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> main_site.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>)[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'createdAt'</span>].agg([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'min'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>])</span>
<span id="cb22-7">session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ((times[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> times[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'min'</span>]).dt.total_seconds() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">60.0</span>).values</span>
<span id="cb22-8"></span>
<span id="cb22-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Count how many links were clicked in each session</span></span>
<span id="cb22-10">link_clicks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> main_site[main_site[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'event'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'link_clicked'</span>].groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>).size()</span>
<span id="cb22-11">session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'links_clicked'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(link_clicks).fillna(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb22-12"></span>
<span id="cb22-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Drop the sessionId column (since it's text) just for the plot, and cap duration the</span></span>
<span id="cb22-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># same way as the box plot above. This clips a copy used only for the chart -</span></span>
<span id="cb22-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># session_metrics itself stays uncapped, since the classifier later in this notebook</span></span>
<span id="cb22-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># trains on the real duration.</span></span>
<span id="cb22-17">plot_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session_metrics[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'total_actions'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'links_clicked'</span>]].copy()</span>
<span id="cb22-18">plot_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plot_data[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>].clip(upper<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>DURATION_CAP_MINUTES)</span>
<span id="cb22-19"></span>
<span id="cb22-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 3. Generate the Scatter Matrix!</span></span>
<span id="cb22-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Needs at least a couple of sessions with values in every column, or pandas' internal</span></span>
<span id="cb22-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># min/max range calculation blows up on an empty array - a fresh/sparse local dev</span></span>
<span id="cb22-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># database (few or no main-site sessions yet) can hit that, so this adapts the same way</span></span>
<span id="cb22-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the classifier evaluation cell further down does.</span></span>
<span id="cb22-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (The '_ =' syntax just suppresses messy text output in Jupyter notebooks)</span></span>
<span id="cb22-26"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(plot_data.dropna()) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb22-27">    _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.plotting.scatter_matrix(</span>
<span id="cb22-28">        plot_data,</span>
<span id="cb22-29">        diagonal<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'kde'</span>,</span>
<span id="cb22-30">        figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>),</span>
<span id="cb22-31">        alpha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>,    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Makes dots slightly transparent to see overlaps</span></span>
<span id="cb22-32">        density_kwds<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'color'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'red'</span>} <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Color the KDE lines red</span></span>
<span id="cb22-33">    )</span>
<span id="cb22-34">    plt.show()</span>
<span id="cb22-35"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb22-36">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Only </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(plot_data)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> session(s) available - too few to plot a scatter matrix."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-15-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>A correlation matrix, visualized as a heatmap - warmer colors mean two metrics move together more strongly. The prose below walks through what these numbers mean for <code>links_clicked</code> and <code>total_actions</code> specifically.</p>
<div id="6318ad28-15af-44a0-92ad-699065947991" class="cell" data-execution_count="15">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1">corr_matrix_viz <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plot_data.corr()</span>
<span id="cb23-2"></span>
<span id="cb23-3">plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span>
<span id="cb23-4">plt.imshow(corr_matrix_viz, cmap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"coolwarm"</span>, vmin<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, vmax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb23-5">plt.xticks(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(corr_matrix_viz.columns)), corr_matrix_viz.columns, rotation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, ha<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"right"</span>)</span>
<span id="cb23-6">plt.yticks(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(corr_matrix_viz.columns)), corr_matrix_viz.columns)</span>
<span id="cb23-7">plt.colorbar(label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Correlation"</span>)</span>
<span id="cb23-8">plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Correlation between session metrics"</span>)</span>
<span id="cb23-9">plt.tight_layout()</span>
<span id="cb23-10">plt.show()</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-16-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="59e7af97-c472-43de-862f-009b279608b6" class="cell" data-execution_count="16">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb24-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Calculate correlations and statistics dynamically</span></span>
<span id="cb24-2">corr_matrix <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plot_data.corr()</span>
<span id="cb24-3">stats <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plot_data.describe()</span>
<span id="cb24-4"></span>
<span id="cb24-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Extract key summary metrics</span></span>
<span id="cb24-6">median_duration <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats.loc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'50%'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>]</span>
<span id="cb24-7">median_actions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats.loc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'50%'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'total_actions'</span>]</span>
<span id="cb24-8">max_duration <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stats.loc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>]</span>
<span id="cb24-9"></span>
<span id="cb24-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Pull individual correlation coefficients (ranges from -1 to 1)</span></span>
<span id="cb24-11">click_duration_corr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> corr_matrix.loc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'links_clicked'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>]</span>
<span id="cb24-12">actions_duration_corr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> corr_matrix.loc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'total_actions'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>]</span>
<span id="cb24-13"></span>
<span id="cb24-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Dynamically evaluate the relationship between link clicks and time on site</span></span>
<span id="cb24-15"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> click_duration_corr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>:</span>
<span id="cb24-16">    feature_value_desc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"strong positive relationship. This proves that clicking links directly drives user retention and keeps people on the site longer"</span></span>
<span id="cb24-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">elif</span> click_duration_corr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>:</span>
<span id="cb24-18">    feature_value_desc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"slight positive relationship, showing some connection between link engagement and session length"</span></span>
<span id="cb24-19"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb24-20">    feature_value_desc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"weak or non-existent relationship. This suggests that link clicks don't impact how long someone stays, meaning they might be clicking an external link and leaving immediately"</span></span>
<span id="cb24-21"></span>
<span id="cb24-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Dynamically analyze user personas based on action vs duration correlation</span></span>
<span id="cb24-23"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> actions_duration_corr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span>:</span>
<span id="cb24-24">    persona_desc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"highly consistent. Users are steadily interacting with the site the entire time they are here (Classic Explorers)."</span></span>
<span id="cb24-25"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb24-26">    persona_desc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fragmented. We have a mix of rapid-fire clickers alongside users who generate very few actions over long stretches of time (Window Shoppers vs. Idle Tabs)."</span></span>
<span id="cb24-27"></span>
<span id="cb24-28"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Format the dynamic print statement</span></span>
<span id="cb24-29"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(</span>
<span id="cb24-30">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"--- EXECUTIVE SUMMARY OF USER BEHAVIOR ---</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb24-31">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Based on our session metrics, a typical user experience lasts for </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>median_duration<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> minutes "</span></span>
<span id="cb24-32">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"and generates </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>median_actions<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> total actions.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb24-33">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"1. IDENTITY USER PERSONAS</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb24-34">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"The relationship between total activity and duration tells us our audience personas are </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>persona_desc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb24-35">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"2. DISCOVER FEATURE VALUE</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb24-36">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"When looking at link engagement, there is a </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>feature_value_desc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb24-37">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"3. SEE YOUR 'AVERAGE' USER EXPERIENCE</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb24-38">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Looking at the distribution curves, the shape of our traffic shows how varied our audience is. "</span></span>
<span id="cb24-39">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"While our median session length sits comfortably at </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>median_duration<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> minutes, the longest session "</span></span>
<span id="cb24-40">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"shown here reached </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>max_duration<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> minutes (this chart is capped at </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>DURATION_CAP_MINUTES<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> minutes - "</span></span>
<span id="cb24-41">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"see the code above). This spread reveals the true 'shape' of our user base—separating "</span></span>
<span id="cb24-42">    <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"the quick bounce traffic from the deeply engaged power users who exhaustively browse the site."</span></span>
<span id="cb24-43">)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>--- EXECUTIVE SUMMARY OF USER BEHAVIOR ---

Based on our session metrics, a typical user experience lasts for 0.0000 minutes and generates 1.00 total actions.

1. IDENTITY USER PERSONAS
The relationship between total activity and duration tells us our audience personas are fragmented. We have a mix of rapid-fire clickers alongside users who generate very few actions over long stretches of time (Window Shoppers vs. Idle Tabs).

2. DISCOVER FEATURE VALUE
When looking at link engagement, there is a slight positive relationship, showing some connection between link engagement and session length.

3. SEE YOUR 'AVERAGE' USER EXPERIENCE
Looking at the distribution curves, the shape of our traffic shows how varied our audience is. While our median session length sits comfortably at 0.0000 minutes, the longest session shown here reached 100.0000 minutes (this chart is capped at 100 minutes - see the code above). This spread reveals the true 'shape' of our user base—separating the quick bounce traffic from the deeply engaged power users who exhaustively browse the site.</code></pre>
</div>
</div>
</section>
<section id="classifying-contact-interest" class="level2">
<h2 class="anchored" data-anchor-id="classifying-contact-interest">Classifying Contact Interest</h2>
<p><code>session_metrics</code> above already looks like a supervised learning setup: numeric features per session (<code>total_actions</code>, <code>duration_minutes</code>, <code>links_clicked</code>) with an obvious target missing. Nothing in this schema hands us a class to predict — so let’s engineer one instead of only clustering.</p>
<p><strong>Label:</strong> did the session ever show interest in the Contact section — i.e.&nbsp;a <code>section_viewed</code> or <code>nav_clicked</code> event with <code>section: "contact"</code>? That’s a reasonable proxy for “this visitor was interested enough to consider reaching out,” and it turns the same session-level features into a decision tree classification problem.</p>
<div id="c17af984-8540-4457-91ff-a53aa47feafe" class="cell" data-execution_count="17">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Add max scroll depth reached per session as another behavioral feature</span></span>
<span id="cb26-2">max_scroll <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> scroll_data.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>)[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'depth'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>()</span>
<span id="cb26-3">session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max_scroll_depth'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(max_scroll).fillna(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb26-4"></span>
<span id="cb26-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Label each session: did it ever show interest in the Contact section?</span></span>
<span id="cb26-6">contact_events <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> main_site[main_site[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'event'</span>].isin([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'section_viewed'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'nav_clicked'</span>])]</span>
<span id="cb26-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># .apply() on an empty Series returns a result that doesn't line up as a boolean mask</span></span>
<span id="cb26-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (indexing with it collapses to a 0-column frame), so a sparse/empty local dev dataset</span></span>
<span id="cb26-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># needs this handled explicitly rather than falling through to the apply/filter below.</span></span>
<span id="cb26-10"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(contact_events) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb26-11">    is_contact <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> contact_events[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'properties'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">lambda</span> p: p.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'section'</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'contact'</span>)</span>
<span id="cb26-12">    contact_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(contact_events[is_contact][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>])</span>
<span id="cb26-13"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb26-14">    contact_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>()</span>
<span id="cb26-15">session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'contact_interest'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>].isin(contact_sessions)</span>
<span id="cb26-16"></span>
<span id="cb26-17">session_metrics[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'total_actions'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'links_clicked'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max_scroll_depth'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'contact_interest'</span>]]</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="17">
<div>
<div>


<table class="dataframe table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">sessionId</th>
<th data-quarto-table-cell-role="th">total_actions</th>
<th data-quarto-table-cell-role="th">duration_minutes</th>
<th data-quarto-table-cell-role="th">links_clicked</th>
<th data-quarto-table-cell-role="th">max_scroll_depth</th>
<th data-quarto-table-cell-role="th">contact_interest</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>00bsroi4eesdbmrk9eb4n</td>
<td>1</td>
<td>0.000000</td>
<td>0.0</td>
<td>0.0</td>
<td>False</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>010syba918vnemtnnzpxy</td>
<td>1</td>
<td>0.000000</td>
<td>0.0</td>
<td>0.0</td>
<td>False</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2</td>
<td>03gvoia5f6i8msg8xxsy</td>
<td>1</td>
<td>0.000000</td>
<td>0.0</td>
<td>0.0</td>
<td>False</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">3</td>
<td>0brdpxf1ghbomqzjqplv</td>
<td>1</td>
<td>0.000000</td>
<td>0.0</td>
<td>0.0</td>
<td>False</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">4</td>
<td>0e2kau1yk6pmt6kifwg</td>
<td>1</td>
<td>0.000000</td>
<td>0.0</td>
<td>0.0</td>
<td>False</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">501</td>
<td>zibdt9s92bemqu5usva</td>
<td>1</td>
<td>0.000000</td>
<td>0.0</td>
<td>0.0</td>
<td>False</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">502</td>
<td>zoarkshcbimqxb7b2e</td>
<td>2</td>
<td>0.000069</td>
<td>0.0</td>
<td>0.0</td>
<td>False</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">503</td>
<td>zp3lnqs8s2emubj6kp5</td>
<td>1</td>
<td>0.000000</td>
<td>0.0</td>
<td>0.0</td>
<td>False</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">504</td>
<td>ztk0odbt8fsmr8hq4ok</td>
<td>1</td>
<td>0.000000</td>
<td>0.0</td>
<td>0.0</td>
<td>False</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">505</td>
<td>zwl6hocmtnmreaq821</td>
<td>5</td>
<td>0.730516</td>
<td>0.0</td>
<td>50.0</td>
<td>False</td>
</tr>
</tbody>
</table>

<p>506 rows × 6 columns</p>
</div>
</div>
</div>
</div>
<p>Each row above is one session with its behavioral features (<code>total_actions</code>, <code>duration_minutes</code>, <code>links_clicked</code>, <code>max_scroll_depth</code>) alongside the engineered <code>contact_interest</code> label - this is the exact table the classifier below is trained on.</p>
<div id="cf61d725-c4a3-48ca-81ae-fc632dab3f21" class="cell" data-execution_count="18">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb27-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> sklearn.tree</span>
<span id="cb27-2"></span>
<span id="cb27-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. Pick the behavioral features and the engineered label</span></span>
<span id="cb27-4">feature_cols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'total_actions'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'duration_minutes'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'links_clicked'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max_scroll_depth'</span>]</span>
<span id="cb27-5">X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session_metrics[feature_cols].values</span>
<span id="cb27-6">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'contact_interest'</span>].astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>).values</span>
<span id="cb27-7"></span>
<span id="cb27-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. Fit a shallow decision tree (kept shallow so it stays readable while the dataset is small).</span></span>
<span id="cb27-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Needs at least one main-site session to fit at all - a fresh/empty local dev database can</span></span>
<span id="cb27-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># have zero, so this (and the two cells below that depend on contact_classifier) adapt the</span></span>
<span id="cb27-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># same way the rest of this notebook does.</span></span>
<span id="cb27-12"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(session_metrics) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb27-13">    contact_classifier <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sklearn.tree.DecisionTreeClassifier(max_depth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb27-14">    contact_classifier.fit(X, y)</span>
<span id="cb27-15">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 3. Explain the tree as text</span></span>
<span id="cb27-16">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(sklearn.tree.export_text(contact_classifier, feature_names<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>feature_cols))</span>
<span id="cb27-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb27-18">    contact_classifier <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb27-19">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"No main-site sessions available - skipping the decision tree."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>|--- max_scroll_depth &lt;= 62.50
|   |--- links_clicked &lt;= 0.50
|   |   |--- duration_minutes &lt;= 0.00
|   |   |   |--- class: 0
|   |   |--- duration_minutes &gt;  0.00
|   |   |   |--- class: 0
|   |--- links_clicked &gt;  0.50
|   |   |--- duration_minutes &lt;= 0.07
|   |   |   |--- class: 0
|   |   |--- duration_minutes &gt;  0.07
|   |   |   |--- class: 0
|--- max_scroll_depth &gt;  62.50
|   |--- max_scroll_depth &lt;= 87.50
|   |   |--- duration_minutes &lt;= 0.67
|   |   |   |--- class: 1
|   |   |--- duration_minutes &gt;  0.67
|   |   |   |--- class: 0
|   |--- max_scroll_depth &gt;  87.50
|   |   |--- class: 1
</code></pre>
</div>
</div>
<div id="1f269b5c-b4c8-42f0-82bf-3f4363b48736" class="cell" data-execution_count="19">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb29" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb29-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Visualize the same tree</span></span>
<span id="cb29-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> contact_classifier <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb29-3">    plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span>
<span id="cb29-4">    _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sklearn.tree.plot_tree(</span>
<span id="cb29-5">        contact_classifier,</span>
<span id="cb29-6">        feature_names<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>feature_cols,</span>
<span id="cb29-7">        class_names<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'no_contact_interest'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'contact_interest'</span>],</span>
<span id="cb29-8">        filled<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span></span>
<span id="cb29-9">    )</span>
<span id="cb29-10"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb29-11">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"No classifier to visualize."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-20-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p><strong>Reading the tree:</strong> each split asks a yes/no question about one feature - true goes left, false goes right. <code>class: 1</code> (<code>contact_interest</code>) leaves show in a warmer shade in the plot above, <code>class: 0</code> in a cooler one. The text dump above and this plot describe the exact same tree; the plot’s easier to scan, the text is easier to copy or quote.</p>
<section id="evaluating-the-classifier" class="level3">
<h3 class="anchored" data-anchor-id="evaluating-the-classifier">Evaluating the Classifier</h3>
<p>Accuracy alone can be misleading, so this checks the tree’s held-out accuracy alongside a confusion matrix - see Tools and Techniques for what each metric means.</p>
<div id="2da0a8cf-1a05-4ceb-ba00-2fb6a7701b3b" class="cell" data-execution_count="20">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb30" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb30-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># How good is the classifier? This adapts to however much data actually exists at render</span></span>
<span id="cb30-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># time below a per-class threshold a held-out split isn't meaningful, so we fall back to training accuracy.</span></span>
<span id="cb30-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.model_selection <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> train_test_split</span>
<span id="cb30-4"></span>
<span id="cb30-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> contact_classifier <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb30-6">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"No classifier to evaluate."</span>)</span>
<span id="cb30-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb30-8">    class_counts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'contact_interest'</span>].value_counts()</span>
<span id="cb30-9">    min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> class_counts.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>()</span>
<span id="cb30-10">    min_per_class_for_split <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb30-11"></span>
<span id="cb30-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> min_per_class_for_split:</span>
<span id="cb30-13">        X_train, X_test, y_train, y_test <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_test_split(</span>
<span id="cb30-14">            X, y, test_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, stratify<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>y, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span></span>
<span id="cb30-15">        )</span>
<span id="cb30-16">        eval_classifier <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sklearn.tree.DecisionTreeClassifier(max_depth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb30-17">        eval_classifier.fit(X_train, y_train)</span>
<span id="cb30-18">        accuracy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> eval_classifier.score(X_test, y_test)</span>
<span id="cb30-19">        <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> ConfusionMatrixDisplay</span>
<span id="cb30-20"></span>
<span id="cb30-21">        ConfusionMatrixDisplay.from_estimator(</span>
<span id="cb30-22">            eval_classifier, X_test, y_test,</span>
<span id="cb30-23">            display_labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'no_contact_interest'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'contact_interest'</span>]</span>
<span id="cb30-24">        )</span>
<span id="cb30-25">        plt.show()</span>
<span id="cb30-26">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(</span>
<span id="cb30-27">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(session_metrics)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions available (</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>class_counts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>to_dict()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> by class) - "</span></span>
<span id="cb30-28">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"enough per class to hold out a test set.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb30-29">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Trained on </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(X_train)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, tested on </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(X_test)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> held-out sessions.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb30-30">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Held-out accuracy: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>accuracy<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb30-31">        )</span>
<span id="cb30-32">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb30-33">        accuracy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> contact_classifier.score(X, y)</span>
<span id="cb30-34">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(</span>
<span id="cb30-35">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Only </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(session_metrics)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions available (</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>class_counts<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>to_dict()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> by class) - "</span></span>
<span id="cb30-36">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"too few per class to hold out a meaningful test set.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb30-37">            <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Training accuracy (read skeptically - not a generalization estimate): </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>accuracy<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb30-38">        )</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-21-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>506 sessions available ({False: 461, True: 45} by class) - enough per class to hold out a test set.
Trained on 354, tested on 152 held-out sessions.
Held-out accuracy: 0.96</code></pre>
</div>
</div>
<p><strong>Note on the accuracy above:</strong> like every other cell in this notebook, this reruns against whatever <code>AnalyticsEvent</code> rows actually exist at render time - local dev data when run locally, real production data at each <code>publish:notes</code> build (see CI). The evaluation cell adapts to that automatically: below a per-class sample threshold it falls back to training accuracy, which should be read skeptically (the tree is being scored on data it already saw); once enough sessions accumulate per class in production, it switches to a genuine held-out train/test split instead.</p>
<p><strong>Precision, recall, and F1</strong> give a fuller picture than accuracy alone, especially since one class may end up rarer than the other once real production data accumulates.</p>
<div id="59e136f2-6d58-4261-8b07-9f6d187b02e2" class="cell" data-execution_count="21">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb32" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb32-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> precision_score, recall_score, f1_score</span>
<span id="cb32-2"></span>
<span id="cb32-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> contact_classifier <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">and</span> min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> min_per_class_for_split:</span>
<span id="cb32-4">    predicted <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> eval_classifier.predict(X_test)</span>
<span id="cb32-5">    precision <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> precision_score(y_test, predicted, zero_division<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb32-6">    recall <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> recall_score(y_test, predicted, zero_division<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb32-7">    f1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> f1_score(y_test, predicted, zero_division<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb32-8">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Precision: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>precision<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, Recall: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>recall<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, F1: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>f1<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb32-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb32-10">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Only </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(session_metrics)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions available - too few per class for a held-out precision/recall/F1 evaluation yet."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Precision: 1.00, Recall: 0.57, F1: 0.73</code></pre>
</div>
</div>
</section>
<section id="why-one-split-isnt-enough" class="level3">
<h3 class="anchored" data-anchor-id="why-one-split-isnt-enough">Why One Split Isn’t Enough</h3>
<p>The decision tree above was evaluated on one particular train/test split. But is that split representative? Below, the same idea - picking the best KNN <code>n_neighbors</code> - is repeated across two different random splits, to see whether the “best” choice actually changes depending on how the data happens to be divided.</p>
<div id="255a7eae-a19d-4dea-b947-e2bee8b62a65" class="cell" data-execution_count="22">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb34" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb34-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.neighbors <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> KNeighborsClassifier</span>
<span id="cb34-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.model_selection <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> train_test_split</span>
<span id="cb34-3"></span>
<span id="cb34-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> contact_classifier <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">and</span> min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> min_per_class_for_split:</span>
<span id="cb34-5">    n_neighbors_range <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>]</span>
<span id="cb34-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> seed <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>]:</span>
<span id="cb34-7">        Xtr, Xte, ytr, yte <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_test_split(X, y, test_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>, stratify<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>y, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>seed)</span>
<span id="cb34-8">        scores <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {k: KNeighborsClassifier(n_neighbors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>k).fit(Xtr, ytr).score(Xte, yte) <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> k <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> n_neighbors_range}</span>
<span id="cb34-9">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"random_state=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>seed<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: best n_neighbors=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(scores, key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>scores.get)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">  scores=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>scores<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb34-10"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb34-11">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Not enough sessions per class to demonstrate split instability yet."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>random_state=1: best n_neighbors=3  scores={1: 0.9736842105263158, 3: 0.9802631578947368, 5: 0.9736842105263158, 7: 0.9671052631578947, 9: 0.9671052631578947}
random_state=42: best n_neighbors=1  scores={1: 0.9736842105263158, 3: 0.9736842105263158, 5: 0.9671052631578947, 7: 0.9605263157894737, 9: 0.9605263157894737}</code></pre>
</div>
</div>
</section>
<section id="cross-validation" class="level3">
<h3 class="anchored" data-anchor-id="cross-validation">Cross-Validation</h3>
<p>Cross-validation fixes the instability shown above by repeating the evaluation across multiple splits and reporting a distribution rather than a single number.</p>
<div id="c83771fc-970f-466e-ad0d-765b56cbbc38" class="cell" data-execution_count="23">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb36" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb36-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.model_selection <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> cross_val_score</span>
<span id="cb36-2"></span>
<span id="cb36-3">cv_folds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span></span>
<span id="cb36-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> contact_classifier <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">and</span> min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> cv_folds:</span>
<span id="cb36-5">    cv_scores <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cross_val_score(sklearn.tree.DecisionTreeClassifier(max_depth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>), X, y, cv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cv_folds)</span>
<span id="cb36-6">    plt.boxplot(cv_scores)</span>
<span id="cb36-7">    plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Accuracy"</span>)</span>
<span id="cb36-8">    plt.title(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cv_folds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">-fold CV Accuracy"</span>)</span>
<span id="cb36-9">    plt.show()</span>
<span id="cb36-10">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Mean: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cv_scores<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>mean()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, Std-dev: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cv_scores<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>std()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb36-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb36-12">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Need at least </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cv_folds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions in the smaller class for </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cv_folds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">-fold CV."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-24-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>Mean: 0.96, Std-dev: 0.02</code></pre>
</div>
</div>
</section>
<section id="overfitting-how-deep-should-the-tree-be" class="level3">
<h3 class="anchored" data-anchor-id="overfitting-how-deep-should-the-tree-be">Overfitting: How Deep Should the Tree Be?</h3>
<p>The tree above was capped at <code>max_depth=3</code> somewhat arbitrarily. Sweeping over depth and comparing training accuracy to held-out test accuracy shows why: as depth increases, training accuracy climbs toward 100% while test accuracy plateaus or drops - the textbook shape of overfitting.</p>
<div id="9c851ca9-90d7-47fd-a2bf-2b30477e8b53" class="cell" data-execution_count="24">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb38" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb38-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> min_per_class_for_split:</span>
<span id="cb38-2">    depths <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span>
<span id="cb38-3">    rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb38-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> d <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> depths:</span>
<span id="cb38-5">        tree <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sklearn.tree.DecisionTreeClassifier(max_depth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>d).fit(X_train, y_train)</span>
<span id="cb38-6">        rows.append({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"max_depth"</span>: d, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train"</span>: tree.score(X_train, y_train), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test"</span>: tree.score(X_test, y_test)})</span>
<span id="cb38-7">    depth_accuracy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(rows)</span>
<span id="cb38-8"></span>
<span id="cb38-9">    plt.plot(depth_accuracy[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"max_depth"</span>], depth_accuracy[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"train"</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ro-"</span>, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Train"</span>)</span>
<span id="cb38-10">    plt.plot(depth_accuracy[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"max_depth"</span>], depth_accuracy[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"test"</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bv--"</span>, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Test"</span>)</span>
<span id="cb38-11">    plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"max_depth"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Accuracy"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> plt.legend()</span>
<span id="cb38-12">    plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Decision Tree: train vs. test accuracy by depth"</span>)</span>
<span id="cb38-13">    plt.show()</span>
<span id="cb38-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb38-15">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Not enough sessions per class for a train/test overfitting curve yet."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-25-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="comparing-classifiers" class="level3">
<h3 class="anchored" data-anchor-id="comparing-classifiers">Comparing Classifiers</h3>
<p>Six classifiers - see Tools and Techniques for what each one does - evaluated with the same cross-validation used above, including a <code>Dummy</code> baseline that always guesses the majority class. If the real classifiers aren’t clearly beating Dummy, they aren’t learning much from the data.</p>
<div id="17f95400-86e4-462b-b53a-7df10eca5233" class="cell" data-execution_count="25">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb39" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb39-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> sklearn.neighbors</span>
<span id="cb39-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> sklearn.ensemble</span>
<span id="cb39-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> sklearn.naive_bayes</span>
<span id="cb39-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.dummy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> DummyClassifier</span>
<span id="cb39-5"></span>
<span id="cb39-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> contact_classifier <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">and</span> min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> cv_folds:</span>
<span id="cb39-7">    n_neighbors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># can't exceed the smallest class size</span></span>
<span id="cb39-8">    models <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb39-9">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Decision Tree"</span>: sklearn.tree.DecisionTreeClassifier(max_depth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb39-10">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"K-Nearest Neighbors"</span>: sklearn.neighbors.KNeighborsClassifier(n_neighbors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_neighbors),</span>
<span id="cb39-11">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Random Forest"</span>: sklearn.ensemble.RandomForestClassifier(n_estimators<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, max_depth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>),</span>
<span id="cb39-12">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bagging"</span>: sklearn.ensemble.BaggingClassifier(</span>
<span id="cb39-13">            estimator<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>sklearn.tree.DecisionTreeClassifier(max_depth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>), n_estimators<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span></span>
<span id="cb39-14">        ),</span>
<span id="cb39-15">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Gaussian Naive Bayes"</span>: sklearn.naive_bayes.GaussianNB(),</span>
<span id="cb39-16">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Dummy (baseline)"</span>: DummyClassifier(strategy<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"most_frequent"</span>),</span>
<span id="cb39-17">    }</span>
<span id="cb39-18">    comparison <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame([</span>
<span id="cb39-19">        {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"model"</span>: name, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean_accuracy"</span>: cross_val_score(model, X, y, cv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cv_folds).mean()}</span>
<span id="cb39-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> name, model <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> models.items()</span>
<span id="cb39-21">    ]).sort_values(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean_accuracy"</span>, ascending<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb39-22"></span>
<span id="cb39-23">    comparison.plot.bar(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"model"</span>, y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean_accuracy"</span>, legend<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb39-24">    plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mean CV Accuracy"</span>)</span>
<span id="cb39-25">    plt.xticks(rotation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>)</span>
<span id="cb39-26">    plt.show()</span>
<span id="cb39-27">    comparison</span>
<span id="cb39-28"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb39-29">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Need at least </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cv_folds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions in the smaller class to compare classifiers."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-26-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="roc-curves" class="level3">
<h3 class="anchored" data-anchor-id="roc-curves">ROC Curves</h3>
<p>Accuracy and even F1 collapse a classifier’s behavior into one number at one decision threshold. ROC curves show the tradeoff between true-positive rate and false-positive rate across <em>every</em> possible threshold - the closer a curve hugs the top-left corner, the better. The diagonal dashed line is what the Dummy baseline should trace, since it uses no information from the features at all.</p>
<div id="fc7b4dc9-1a5d-4be4-bebf-374d4175b1ab" class="cell" data-execution_count="26">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb40" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb40-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> roc_curve</span>
<span id="cb40-2"></span>
<span id="cb40-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> min_per_class_for_split:</span>
<span id="cb40-4">    plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb40-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> name, model <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> models.items():</span>
<span id="cb40-6">        model.fit(X_train, y_train)</span>
<span id="cb40-7">        probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.predict_proba(X_test)[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb40-8">        fpr, tpr, _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> roc_curve(y_test, probs)</span>
<span id="cb40-9">        plt.plot(fpr, tpr, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>name)</span>
<span id="cb40-10">    plt.plot([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'k--'</span>, label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Random guess"</span>)</span>
<span id="cb40-11">    plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"False Positive Rate"</span>)</span>
<span id="cb40-12">    plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"True Positive Rate"</span>)</span>
<span id="cb40-13">    plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ROC curves: contact_interest classifiers"</span>)</span>
<span id="cb40-14">    plt.legend(fontsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)</span>
<span id="cb40-15">    plt.show()</span>
<span id="cb40-16"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb40-17">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Not enough sessions per class for a held-out ROC comparison yet."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-27-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="tuning-knn" class="level3">
<h3 class="anchored" data-anchor-id="tuning-knn">Tuning KNN</h3>
<p>KNN specifically has two things worth tuning: which distance <strong>metric</strong> it uses, and whether features are <strong>scaled</strong> first. Scaling matters here because KNN is distance-based, and <code>duration_minutes</code> (ranging up to ~100) would otherwise dominate the distance calculation over <code>links_clicked</code> (ranging 0-5).</p>
<div id="d17255be-571a-4571-9230-44332616b0af" class="cell" data-execution_count="27">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb41" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb41-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> contact_classifier <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">and</span> min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> cv_folds:</span>
<span id="cb41-2">    n_neighbors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb41-3">    metric_scores <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb41-4">        metric: cross_val_score(</span>
<span id="cb41-5">            sklearn.neighbors.KNeighborsClassifier(n_neighbors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_neighbors, metric<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>metric), X, y, cv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cv_folds</span>
<span id="cb41-6">        ).mean()</span>
<span id="cb41-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> metric <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"euclidean"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"manhattan"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cosine"</span>]</span>
<span id="cb41-8">    }</span>
<span id="cb41-9">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(metric_scores)</span>
<span id="cb41-10"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb41-11">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Need at least </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cv_folds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions in the smaller class to compare KNN metrics."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>{'euclidean': np.float64(0.9604154533100369), 'manhattan': np.float64(0.9604154533100369), 'cosine': np.float64(0.9228499320520287)}</code></pre>
</div>
</div>
<div id="632b2a44-b55b-4132-bcf4-d85971829df6" class="cell" data-execution_count="28">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb43" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb43-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.preprocessing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> StandardScaler</span>
<span id="cb43-2"></span>
<span id="cb43-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> contact_classifier <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">and</span> min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> cv_folds:</span>
<span id="cb43-4">    X_scaled <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> StandardScaler().fit_transform(X)</span>
<span id="cb43-5">    n_neighbors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb43-6">    unscaled_score <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cross_val_score(sklearn.neighbors.KNeighborsClassifier(n_neighbors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_neighbors), X, y, cv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cv_folds).mean()</span>
<span id="cb43-7">    scaled_score <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cross_val_score(sklearn.neighbors.KNeighborsClassifier(n_neighbors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_neighbors), X_scaled, y, cv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cv_folds).mean()</span>
<span id="cb43-8">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"KNN mean CV accuracy — unscaled: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>unscaled_score<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">, scaled: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>scaled_score<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb43-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb43-10">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Need at least </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cv_folds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions in the smaller class to compare scaled vs. unscaled features."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>KNN mean CV accuracy — unscaled: 0.96, scaled: 0.97</code></pre>
</div>
</div>
</section>
<section id="systematic-hyperparameter-search" class="level3">
<h3 class="anchored" data-anchor-id="systematic-hyperparameter-search">Systematic Hyperparameter Search</h3>
<p>Rather than tuning one hyperparameter at a time, <code>GridSearchCV</code> searches every combination of a parameter grid at once, cross-validating each - run here for both the Decision Tree and KNN, on both scaled and unscaled features.</p>
<div id="d40b2c69-9331-498f-9463-70b6845bf00e" class="cell" data-execution_count="29">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb45" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb45-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.model_selection <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> GridSearchCV</span>
<span id="cb45-2"></span>
<span id="cb45-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> contact_classifier <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">and</span> min_class_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> cv_folds:</span>
<span id="cb45-4">    tree_grid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"criterion"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gini"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"entropy"</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"max_depth"</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"min_samples_split"</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]}</span>
<span id="cb45-5">    knn_grid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb45-6">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n_neighbors"</span>: [k <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> k <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> min_class_count],</span>
<span id="cb45-7">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"metric"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"euclidean"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"manhattan"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cosine"</span>],</span>
<span id="cb45-8">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"weights"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"uniform"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"distance"</span>],</span>
<span id="cb45-9">    }</span>
<span id="cb45-10"></span>
<span id="cb45-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> label, feats <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> [(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"unscaled"</span>, X), (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scaled"</span>, X_scaled)]:</span>
<span id="cb45-12">        tree_search <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> GridSearchCV(sklearn.tree.DecisionTreeClassifier(), tree_grid, cv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cv_folds).fit(feats, y)</span>
<span id="cb45-13">        knn_search <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> GridSearchCV(sklearn.neighbors.KNeighborsClassifier(), knn_grid, cv<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cv_folds).fit(feats, y)</span>
<span id="cb45-14">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"[</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>label<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">] best tree: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>tree_search<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>best_params_<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> -&gt; </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>tree_search<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>best_score_<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb45-15">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"[</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>label<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">] best knn:  </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>knn_search<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>best_params_<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> -&gt; </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>knn_search<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>best_score_<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb45-16"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb45-17">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Need at least </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cv_folds<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions in the smaller class to run GridSearchCV."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>[unscaled] best tree: {'criterion': 'gini', 'max_depth': 2, 'min_samples_split': 2} -&gt; 0.97
[unscaled] best knn:  {'metric': 'euclidean', 'n_neighbors': 5, 'weights': 'distance'} -&gt; 0.97
[scaled] best tree: {'criterion': 'gini', 'max_depth': 2, 'min_samples_split': 2} -&gt; 0.97
[scaled] best knn:  {'metric': 'euclidean', 'n_neighbors': 5, 'weights': 'uniform'} -&gt; 0.97</code></pre>
</div>
</div>
</section>
<section id="visualizing-sessions-in-feature-space" class="level3">
<h3 class="anchored" data-anchor-id="visualizing-sessions-in-feature-space">Visualizing Sessions in Feature Space</h3>
<p>With only 4 features, PCA here isn’t really reducing dimensionality - it’s mainly a convenient way to check by eye whether <code>contact_interest</code> sessions visually separate from the rest at all.</p>
<div id="2130f509-b6b1-401f-b75c-410a574f8353" class="cell" data-execution_count="30">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb47" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb47-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> contact_classifier <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">and</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(session_metrics) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb47-2">    X_scaled_for_pca <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> StandardScaler().fit_transform(X)</span>
<span id="cb47-3">    pca_2d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PCA(n_components<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).fit_transform(X_scaled_for_pca)</span>
<span id="cb47-4"></span>
<span id="cb47-5">    plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span>
<span id="cb47-6">    plt.scatter(pca_2d[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], pca_2d[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], c<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>y, cmap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"coolwarm"</span>, edgecolor<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"k"</span>)</span>
<span id="cb47-7">    plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC1"</span>)</span>
<span id="cb47-8">    plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PC2"</span>)</span>
<span id="cb47-9">    plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sessions in PCA space, colored by contact_interest"</span>)</span>
<span id="cb47-10">    plt.show()</span>
<span id="cb47-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb47-12">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Not enough sessions to plot a PCA scatter yet."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-31-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
</section>
<section id="clustering-sessions-into-behavioral-groups" class="level2">
<h2 class="anchored" data-anchor-id="clustering-sessions-into-behavioral-groups">Clustering Sessions into Behavioral Groups</h2>
<p>Everything above predicts a label we engineered ourselves (<code>contact_interest</code>). This section instead asks an unsupervised question: without any labels at all, do sessions naturally fall into distinct behavioral groups? Visualizing the Data’s executive summary speculated about “user personas” from a single correlation coefficient - this section checks that claim with an actual model instead.</p>
<p>As with KNN above, these algorithms are distance-based, so features are scaled first:</p>
<div id="bf524b58-29f3-49fb-954a-8ecabcabc23c" class="cell" data-execution_count="31">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb48" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb48-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.preprocessing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> StandardScaler</span>
<span id="cb48-2"></span>
<span id="cb48-3">cluster_features <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> StandardScaler().fit_transform(X)</span>
<span id="cb48-4">n_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(session_metrics)</span></code></pre></div>
</details>
</div>
<section id="k-means-elbow-and-silhouette-methods" class="level3">
<h3 class="anchored" data-anchor-id="k-means-elbow-and-silhouette-methods">K-Means: Elbow and Silhouette Methods</h3>
<p>K-means needs to be told how many clusters (<em>k</em>) to look for. The elbow method (inertia - how tightly packed each cluster is) and the silhouette score (how well-separated clusters are) both help pick a reasonable value.</p>
<div id="70fae64f-9941-4bfc-b839-ed1e75dee865" class="cell" data-execution_count="32">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb49" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb49-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.cluster <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> KMeans</span>
<span id="cb49-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.metrics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> silhouette_score</span>
<span id="cb49-3"></span>
<span id="cb49-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> n_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>:</span>
<span id="cb49-5">    k_range <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, n_sessions))</span>
<span id="cb49-6">    inertia <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [KMeans(n_clusters<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>k, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>).fit(cluster_features).inertia_ <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> k <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> k_range]</span>
<span id="cb49-7">    silhouette <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb49-8">        silhouette_score(cluster_features, KMeans(n_clusters<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>k, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>).fit_predict(cluster_features))</span>
<span id="cb49-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> k <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> k_range</span>
<span id="cb49-10">    ]</span>
<span id="cb49-11"></span>
<span id="cb49-12">    fig, axes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb49-13">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].plot(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(k_range), inertia, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bx-'</span>)</span>
<span id="cb49-14">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"k"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Inertia"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Elbow method"</span>)</span>
<span id="cb49-15">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].plot(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(k_range), silhouette, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bx-'</span>)</span>
<span id="cb49-16">    axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"k"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Silhouette score"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> axes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].set_title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Silhouette method"</span>)</span>
<span id="cb49-17">    plt.tight_layout()</span>
<span id="cb49-18">    plt.show()</span>
<span id="cb49-19"></span>
<span id="cb49-20">    best_k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(k_range)[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(np.argmax(silhouette))]</span>
<span id="cb49-21">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Best k by silhouette: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>best_k<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb49-22"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb49-23">    best_k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb49-24">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Only </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_sessions<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions - too few to sweep k meaningfully."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-33-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
<div class="cell-output cell-output-stdout">
<pre><code>Best k by silhouette: 4</code></pre>
</div>
</div>
<div id="9ce9ab2a-1dd2-48cc-a66c-63d2a827cd39" class="cell" data-execution_count="33">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb51" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb51-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Fit at the chosen k and profile each cluster - this is what turns the "user personas"</span></span>
<span id="cb51-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># language above into an actual finding instead of an eyeballed guess.</span></span>
<span id="cb51-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> best_k <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb51-4">    kmeans <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> KMeans(n_clusters<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>best_k, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>).fit(cluster_features)</span>
<span id="cb51-5">    session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'cluster'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> kmeans.labels_</span>
<span id="cb51-6">    session_metrics.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'cluster'</span>)[feature_cols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'contact_interest'</span>]].mean()</span>
<span id="cb51-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb51-8">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Skipping cluster profiling - not enough sessions."</span>)</span></code></pre></div>
</details>
</div>
</section>
<section id="hierarchical-clustering" class="level3">
<h3 class="anchored" data-anchor-id="hierarchical-clustering">Hierarchical Clustering</h3>
<p>Unlike K-means, hierarchical clustering doesn’t require picking <em>k</em> upfront - it builds a full tree of nested groupings, visualized as a dendrogram. This is especially readable at this dataset’s small session count, where the same dendrogram on a much larger dataset would be unreadable.</p>
<div id="78544e68-88f5-460f-8392-d8d53f6949ae" class="cell" data-execution_count="34">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb52" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb52-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> scipy.cluster.hierarchy <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> hierarchy</span>
<span id="cb52-2"></span>
<span id="cb52-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> n_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>:</span>
<span id="cb52-4">    linked <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> hierarchy.linkage(cluster_features, method<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ward'</span>)</span>
<span id="cb52-5"></span>
<span id="cb52-6">    plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span>
<span id="cb52-7">    hierarchy.dendrogram(linked, labels<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>].tolist())</span>
<span id="cb52-8">    plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Session (truncated ID)"</span>)</span>
<span id="cb52-9">    plt.ylabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Distance"</span>)</span>
<span id="cb52-10">    plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Session clustering dendrogram"</span>)</span>
<span id="cb52-11">    plt.xticks(rotation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">90</span>)</span>
<span id="cb52-12">    plt.tight_layout()</span>
<span id="cb52-13">    plt.show()</span>
<span id="cb52-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb52-15">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Only </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_sessions<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions - too few for a meaningful dendrogram."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-35-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="dbscan" class="level3">
<h3 class="anchored" data-anchor-id="dbscan">DBSCAN</h3>
<p>DBSCAN groups points by density rather than distance-to-center, and needs an <code>eps</code> (maximum neighbor distance) hyperparameter, estimated below via a k-nearest-neighbor distance plot and then used to fit the model. With this few sessions, don’t be surprised if DBSCAN finds one giant cluster or labels most sessions as noise (<code>-1</code>) - that’s a legitimate result given the data density, not a bug.</p>
<div id="03517ccf-c7c6-40e7-81e7-9aa44d0b7ad6" class="cell" data-execution_count="35">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb53" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb53-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.cluster <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> DBSCAN</span>
<span id="cb53-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.neighbors <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> NearestNeighbors</span>
<span id="cb53-3"></span>
<span id="cb53-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> n_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>:</span>
<span id="cb53-5">    n_neighbors_for_eps <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(feature_cols) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, n_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># lab 8's own rule of thumb: 2x dimensionality</span></span>
<span id="cb53-6"></span>
<span id="cb53-7">    neighbors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> NearestNeighbors(n_neighbors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_neighbors_for_eps).fit(cluster_features)</span>
<span id="cb53-8">    distances, _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> neighbors.kneighbors(cluster_features)</span>
<span id="cb53-9">    distances <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.sort(distances[:, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb53-10"></span>
<span id="cb53-11">    plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb53-12">    plt.plot(distances)</span>
<span id="cb53-13">    plt.xlabel(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Session, sorted by distance"</span>)</span>
<span id="cb53-14">    plt.ylabel(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Distance to </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_neighbors_for_eps<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">th neighbor"</span>)</span>
<span id="cb53-15">    plt.title(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DBSCAN eps estimation"</span>)</span>
<span id="cb53-16">    plt.show()</span>
<span id="cb53-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb53-18">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Only </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_sessions<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions - too few to estimate a stable DBSCAN eps."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/MainSiteData_files/figure-html/cell-36-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="e9ad08ef-dc47-4fa3-a394-bbbe45663a6e" class="cell" data-execution_count="36">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb54" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb54-1">eps <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># replace with whatever value the elbow above actually shows</span></span>
<span id="cb54-2"></span>
<span id="cb54-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> n_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>:</span>
<span id="cb54-4">    dbscan <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DBSCAN(eps<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>eps, min_samples<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_neighbors_for_eps).fit(cluster_features)</span>
<span id="cb54-5">    session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'dbscan_cluster'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dbscan.labels_</span>
<span id="cb54-6">    session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'dbscan_cluster'</span>].value_counts()</span></code></pre></div>
</details>
</div>
</section>
<section id="anomaly-detection" class="level3">
<h3 class="anchored" data-anchor-id="anomaly-detection">Anomaly Detection</h3>
<p>A different unsupervised question: not “what groups exist,” but “which sessions don’t look like the rest.” Three algorithms - see Tools and Techniques - each flag their own outliers; sessions flagged by two or more are the more trustworthy calls, given how easily any single algorithm can be thrown off at this sample size.</p>
<div id="266e8950-8354-442c-a7a3-8094c5b144f6" class="cell" data-execution_count="37">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb55" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb55-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.covariance <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> EllipticEnvelope</span>
<span id="cb55-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.svm <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> OneClassSVM</span>
<span id="cb55-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.neighbors <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> LocalOutlierFactor</span>
<span id="cb55-4"></span>
<span id="cb55-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> n_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>:</span>
<span id="cb55-6">    outliers_fraction <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span></span>
<span id="cb55-7">    n_neighbors_lof <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, n_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb55-8"></span>
<span id="cb55-9">    anomaly_algorithms <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb55-10">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Robust Covariance"</span>: EllipticEnvelope(contamination<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>outliers_fraction, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>),</span>
<span id="cb55-11">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"One-Class SVM"</span>: OneClassSVM(nu<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>outliers_fraction, kernel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rbf"</span>, gamma<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"scale"</span>),</span>
<span id="cb55-12">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Local Outlier Factor"</span>: LocalOutlierFactor(n_neighbors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_neighbors_lof, contamination<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>outliers_fraction),</span>
<span id="cb55-13">    }</span>
<span id="cb55-14"></span>
<span id="cb55-15">    results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sessionId"</span>: session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sessionId"</span>]})</span>
<span id="cb55-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> name, algorithm <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> anomaly_algorithms.items():</span>
<span id="cb55-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">try</span>:</span>
<span id="cb55-18">            <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> name <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Local Outlier Factor"</span>:</span>
<span id="cb55-19">                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># LOF only supports fit_predict in this mode - no separate .fit() then .predict()</span></span>
<span id="cb55-20">                labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> algorithm.fit_predict(cluster_features)</span>
<span id="cb55-21">            <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb55-22">                labels <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> algorithm.fit(cluster_features).predict(cluster_features)</span>
<span id="cb55-23">            results[name] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> labels  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># -1 = outlier, 1 = inlier</span></span>
<span id="cb55-24">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">ValueError</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> e:</span>
<span id="cb55-25">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Robust Covariance needs real spread within its "cleanest" data subset to</span></span>
<span id="cb55-26">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># estimate a covariance matrix at all - real traffic with many near-identical</span></span>
<span id="cb55-27">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># bounce sessions (single pageview, no scroll, no clicks) can make that subset</span></span>
<span id="cb55-28">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># exactly degenerate. Skip just this algorithm rather than failing the cell.</span></span>
<span id="cb55-29">            <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Skipped </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>e<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb55-30"></span>
<span id="cb55-31">    results</span>
<span id="cb55-32"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span>:</span>
<span id="cb55-33">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Only </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>n_sessions<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions - too few to fit anomaly detectors reliably (need &gt;= 10)."</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>Skipped Robust Covariance: The covariance matrix of the support data is equal to 0, try to increase support_fraction</code></pre>
</div>
<div class="cell-output cell-output-stderr">
<pre><code>/usr/local/lib/python3.11/site-packages/sklearn/neighbors/_lof.py:327: UserWarning: Duplicate values are leading to incorrect results. Increase the number of neighbors for more accurate results.
  warnings.warn(</code></pre>
</div>
</div>
<div id="6f13eaba-7f8d-4545-a050-c402af7f8d38" class="cell" data-execution_count="38">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb58" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb58-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> n_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>:</span>
<span id="cb58-2">    algo_cols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [name <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> name <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> anomaly_algorithms <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> name <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> results.columns]</span>
<span id="cb58-3">    results[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"flagged_by"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (results[algo_cols] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb58-4">    results.sort_values(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"flagged_by"</span>, ascending<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span></code></pre></div>
</details>
</div>
<div id="f352c2ac-e6e1-4b2f-9633-76dead41ef68" class="cell" data-execution_count="39">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb59" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb59-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> n_sessions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>:</span>
<span id="cb59-2">    flagged <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> results[results[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"flagged_by"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sessionId"</span>]</span>
<span id="cb59-3">    session_metrics[session_metrics[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sessionId"</span>].isin(flagged)][feature_cols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"contact_interest"</span>]]</span></code></pre></div>
</details>
</div>
</section>
</section>
<section id="association-analysis-what-site-behaviors-go-together" class="level2">
<h2 class="anchored" data-anchor-id="association-analysis-what-site-behaviors-go-together">Association Analysis: What Site Behaviors Go Together</h2>
<p>A third kind of question, distinct from both prediction and clustering: which site behaviors tend to co-occur within the same session? Each session becomes a “basket” of the distinct events it triggered (e.g.&nbsp;<code>section_viewed:contact</code>, <code>scroll_depth:100</code>), borrowing the same asymmetric-binary-attribute idea used for classic market-basket analysis (which products get bought together).</p>
<section id="building-the-baskets" class="level3">
<h3 class="anchored" data-anchor-id="building-the-baskets">Building the Baskets</h3>
<p>Each session’s events, deduplicated to presence/absence per distinct <code>event:property</code> combo - “did this session ever do X,” not how many times.</p>
<div id="631ed1da-c2a6-4d81-b693-eec306feb447" class="cell" data-execution_count="40">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb60" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb60-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">def</span> event_to_item(row):</span>
<span id="cb60-2">    event <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'event'</span>]</span>
<span id="cb60-3">    props <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'properties'</span>]</span>
<span id="cb60-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(props, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">and</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(props) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb60-5">        key <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(props))</span>
<span id="cb60-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">return</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>event<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">:</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>props[key]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb60-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">return</span> event</span>
<span id="cb60-8"></span>
<span id="cb60-9">main_site[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'item'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> main_site.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(event_to_item, axis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb60-10"></span>
<span id="cb60-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># one basket per session: the *set* of distinct items it triggered (order/repeats don't matter)</span></span>
<span id="cb60-12">transactions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> main_site.groupby(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sessionId'</span>)[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'item'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">lambda</span> items: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(items)).tolist()</span>
<span id="cb60-13">all_items <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(item <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> t <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> transactions <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> item <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> t))</span>
<span id="cb60-14"></span>
<span id="cb60-15"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(transactions)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> sessions (transactions), </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(all_items)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> distinct items"</span>)</span>
<span id="cb60-16">all_items</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>506 sessions (transactions), 27 distinct items</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="40">
<pre><code>['link_clicked:ayuda',
 'link_clicked:email',
 'link_clicked:exact',
 'link_clicked:github',
 'link_clicked:notes',
 'link_clicked:old-site',
 'link_clicked:planner',
 'link_clicked:quantum',
 'link_clicked:sky',
 'link_clicked:youtube',
 'link_clicked:zakacat',
 'nav_clicked:about',
 'nav_clicked:contact',
 'nav_clicked:experience',
 'nav_clicked:home',
 'nav_clicked:research',
 'page_load',
 'page_load:atlas',
 'scroll_depth:100',
 'scroll_depth:25',
 'scroll_depth:50',
 'scroll_depth:75',
 'section_viewed:about',
 'section_viewed:contact',
 'section_viewed:experience',
 'section_viewed:research',
 'video_played:atlas_demo_full']</code></pre>
</div>
</div>
</section>
<section id="frequent-itemsets" class="level3">
<h3 class="anchored" data-anchor-id="frequent-itemsets">Frequent Itemsets</h3>
<p>With only a handful of distinct item types, a brute-force check of every combination up to size 3 is fast enough that a specialized algorithm like FP-growth isn’t necessary.</p>
<div id="8883fc7b-c54c-4f03-8ace-f664654fe9e4" class="cell" data-execution_count="41">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb63" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb63-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> itertools</span>
<span id="cb63-2"></span>
<span id="cb63-3">min_support_count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(transactions) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># tune this - see note below</span></span>
<span id="cb63-4"></span>
<span id="cb63-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">def</span> itemset_support_count(itemset, transactions):</span>
<span id="cb63-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> t <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> transactions <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(itemset).issubset(t))</span>
<span id="cb63-7"></span>
<span id="cb63-8">frequent <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb63-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> size <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]:</span>
<span id="cb63-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> combo <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> itertools.combinations(all_items, size):</span>
<span id="cb63-11">        count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> itemset_support_count(combo, transactions)</span>
<span id="cb63-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> min_support_count:</span>
<span id="cb63-13">            frequent.append({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"itemset"</span>: combo, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"support_count"</span>: count, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"support"</span>: count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(transactions)})</span>
<span id="cb63-14"></span>
<span id="cb63-15">frequent_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(frequent).sort_values(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"support"</span>, ascending<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb63-16">frequent_df</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="41">
<div>
<div>


<table class="dataframe table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">itemset</th>
<th data-quarto-table-cell-role="th">support_count</th>
<th data-quarto-table-cell-role="th">support</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>(page_load,)</td>
<td>486</td>
<td>0.960474</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>(section_viewed:about,)</td>
<td>147</td>
<td>0.290514</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2</td>
<td>(page_load, section_viewed:about)</td>
<td>139</td>
<td>0.274704</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</div>
</section>
<section id="association-rules" class="level3">
<h3 class="anchored" data-anchor-id="association-rules">Association Rules</h3>
<p>For every frequent itemset, every way of splitting it into a left-hand and right-hand side becomes a candidate rule, kept if its confidence (how often the right-hand side follows given the left) clears a minimum threshold.</p>
<p><strong>Read any rules found here skeptically</strong> - confidence on a 15-session dataset is extremely noisy (one session flips a ratio by ~7 percentage points), so treat this as “here’s what the mechanism produces,” not “here’s a confirmed finding,” until real production data accumulates.</p>
<div id="f12b7f7b-6c35-4562-8666-6bc8ac3cafe0" class="cell" data-execution_count="42">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb64" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb64-1">support_lookup <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">frozenset</span>(row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'itemset'</span>]): row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'support'</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> _, row <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> frequent_df.iterrows()}</span>
<span id="cb64-2"></span>
<span id="cb64-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">def</span> proper_subsets(s):</span>
<span id="cb64-4">    s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(s)</span>
<span id="cb64-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">return</span> itertools.chain.from_iterable(itertools.combinations(s, r) <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> r <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(s)))</span>
<span id="cb64-6"></span>
<span id="cb64-7">min_confidence <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.6</span></span>
<span id="cb64-8">rules <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb64-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> _, row <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> frequent_df[frequent_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'itemset'</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].iterrows():</span>
<span id="cb64-10">    itemset <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'itemset'</span>]</span>
<span id="cb64-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> left <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> proper_subsets(itemset):</span>
<span id="cb64-12">        left_key <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">frozenset</span>(left)</span>
<span id="cb64-13">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> left_key <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">not</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> support_lookup:</span>
<span id="cb64-14">            <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">continue</span></span>
<span id="cb64-15">        right <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">frozenset</span>(itemset) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> left_key</span>
<span id="cb64-16">        confidence <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'support'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> support_lookup[left_key]</span>
<span id="cb64-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> confidence <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> min_confidence:</span>
<span id="cb64-18">            rules.append({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"left"</span>: left, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"right"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">tuple</span>(right), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"support"</span>: row[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'support'</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"confidence"</span>: confidence})</span>
<span id="cb64-19"></span>
<span id="cb64-20">rules_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(rules).sort_values(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"confidence"</span>, ascending<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb64-21">rules_df</span></code></pre></div>
</details>
<div class="cell-output cell-output-display" data-execution_count="42">
<div>
<div>


<table class="dataframe table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">left</th>
<th data-quarto-table-cell-role="th">right</th>
<th data-quarto-table-cell-role="th">support</th>
<th data-quarto-table-cell-role="th">confidence</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>(section_viewed:about,)</td>
<td>(page_load,)</td>
<td>0.274704</td>
<td>0.945578</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</div>


</section>
</section>
</section>

 ]]></description>
  <category>project</category>
  <category>data-mining</category>
  <category>data</category>
  <guid>https://notes.zakacat.ca/notebooks/MainSiteData.html</guid>
  <pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>History of Quantum Physics and Computing</title>
  <dc:creator>Zak Toews</dc:creator>
  <link>https://notes.zakacat.ca/notebooks/history-of-quantum-physicists.html</link>
  <description><![CDATA[ 




<center>
<section id="history-of-quantum-physics-and-computing" class="level1">
<h1><strong>History of Quantum Physics and Computing</strong></h1>
<section id="ai-assisted-study-guide-built-from-httpsmathshistory.st-andrews.ac.ukbiographies" class="level3">
<h3 class="anchored" data-anchor-id="ai-assisted-study-guide-built-from-httpsmathshistory.st-andrews.ac.ukbiographies">AI assisted study guide built from https://mathshistory.st-andrews.ac.uk/Biographies/</h3>
</section></section></center>


<section id="table-of-contents" class="level1">
<h1>Table of Contents</h1>
<ol type="1">
<li>Leonhard Euler (1707-1783)</li>
<li>Max Planck (1858-1947)</li>
<li>Jacques Hadamard (1865-1963)</li>
<li>Albert Einstein (1879-1955)</li>
<li>Niels Bohr (1885-1962)</li>
<li>Erwin Schrödinger (1887-1961)</li>
<li>Louis de Broglie (1892-1987)</li>
<li>Wolfgang Pauli (1900-1958)</li>
<li>Werner Heisenberg (1901-1976)</li>
<li>John von Neumann (1903-1957)</li>
<li>Felix Bloch (1905-1983)</li>
<li>Claude Shannon (1916-2001)</li>
<li>Paul Dirac (1902-1984)</li>
<li>Richard Feynman (1918-1988)</li>
<li>John Stewart Bell (1928-1990)</li>
</ol>
</section>
<section id="leonhard-euler-1707-1783" class="level1">
<h1>Leonhard Euler (1707-1783)</h1>
<section id="biographical-essentials" class="level2">
<h2 class="anchored" data-anchor-id="biographical-essentials">1. Biographical Essentials</h2>
<ul>
<li><strong>Origin:</strong> Swiss mathematician born in <strong>Basel</strong>.</li>
<li><strong>Education:</strong> Entered the University of Basel at age 13; studied under <strong>Johann Bernoulli</strong>.</li>
<li><strong>Career Path:</strong> * Originally intended for the ministry (theology), but Bernoulli convinced his father of his mathematical genius.
<ul>
<li>Spent most of his career in <strong>St.&nbsp;Petersburg (Russia)</strong> and <strong>Berlin (Prussia)</strong>.</li>
</ul></li>
<li><strong>Resilience:</strong> He lost sight in his right eye in 1735 and became <strong>totally blind</strong> in 1766. Remarkably, he produced nearly half of his total work while blind by dictating to scribes.</li>
</ul>
</section>
<section id="key-contributions-to-mathematical-notation" class="level2">
<h2 class="anchored" data-anchor-id="key-contributions-to-mathematical-notation">2. Key Contributions to Mathematical Notation</h2>
<p>Euler standardized the language of modern mathematics. If you see these on an exam, Euler is the reason: * <strong>Function Notation:</strong> <img src="https://latex.codecogs.com/png.latex?f(x)"> * <strong>The Base of Natural Logarithms:</strong> <img src="https://latex.codecogs.com/png.latex?e"> (approx. 2.718) * <strong>Imaginary Unit:</strong> <img src="https://latex.codecogs.com/png.latex?i%20=%20%5Csqrt%7B-1%7D"> * <strong>Summation Symbol:</strong> <img src="https://latex.codecogs.com/png.latex?%5Csum"> * <strong>Constants:</strong> Popularized <img src="https://latex.codecogs.com/png.latex?%5Cpi"> (ratio of circumference to diameter). * <strong>Trigonometry:</strong> Defined <img src="https://latex.codecogs.com/png.latex?%5Csin,%20%5Ccos,%20%5Ctan"> as functions/ratios rather than just lengths of lines.</p>
</section>
<section id="famous-formulas-theorems" class="level2">
<h2 class="anchored" data-anchor-id="famous-formulas-theorems">3. Famous Formulas &amp; Theorems</h2>
<section id="eulers-identity" class="level3">
<h3 class="anchored" data-anchor-id="eulers-identity">Euler’s Identity</h3>
<p>Often called “the most beautiful equation in mathematics” because it links five fundamental constants (<img src="https://latex.codecogs.com/png.latex?e,%20i,%20%5Cpi,%201,%200">): <img src="https://latex.codecogs.com/png.latex?e%5E%7Bi%5Cpi%7D%20+%201%20=%200"></p>
</section>
<section id="eulers-formula-complex-analysis" class="level3">
<h3 class="anchored" data-anchor-id="eulers-formula-complex-analysis">Euler’s Formula (Complex Analysis)</h3>
<p>The bridge between exponential functions and trigonometry: <img src="https://latex.codecogs.com/png.latex?e%5E%7Bix%7D%20=%20%5Ccos(x)%20+%20i%5Csin(x)"></p>
</section>
<section id="polyhedral-formula-topologygeometry" class="level3">
<h3 class="anchored" data-anchor-id="polyhedral-formula-topologygeometry">Polyhedral Formula (Topology/Geometry)</h3>
<p>For any convex polyhedron with <img src="https://latex.codecogs.com/png.latex?V"> vertices, <img src="https://latex.codecogs.com/png.latex?E"> edges, and <img src="https://latex.codecogs.com/png.latex?F"> faces: <img src="https://latex.codecogs.com/png.latex?V%20-%20E%20+%20F%20=%202"></p>
</section>
</section>
<section id="landmark-problems-fields" class="level2">
<h2 class="anchored" data-anchor-id="landmark-problems-fields">4. Landmark Problems &amp; Fields</h2>
<ul>
<li><strong>Graph Theory:</strong> Solved the <strong>Seven Bridges of Königsberg</strong> problem (1736), proving it was impossible to cross all seven bridges exactly once. This is considered the origin of graph theory and topology.</li>
<li><strong>Calculus of Variations:</strong> Developed the <strong>Euler-Lagrange equation</strong>, fundamental to optimization and physics.</li>
<li><strong>Number Theory:</strong> Proved the <strong>Basel Problem</strong> (sum of reciprocal squares): <img src="https://latex.codecogs.com/png.latex?%5Csum_%7Bn=1%7D%5E%7B%5Cinfty%7D%20%5Cfrac%7B1%7D%7Bn%5E2%7D%20=%20%5Cfrac%7B%5Cpi%5E2%7D%7B6%7D"></li>
<li><strong>Fluid Dynamics:</strong> Developed the <strong>Euler Equations</strong> for the motion of inviscid (frictionless) fluids.</li>
</ul>
</section>
<section id="fun-facts" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts">5. Fun Facts</h2>
<ul>
<li><strong>Fact:</strong> Euler was the most prolific mathematician in history (over 850 publications).</li>
<li><strong>Fact:</strong> He introduced the use of <img src="https://latex.codecogs.com/png.latex?a,%20b,%20c"> for triangle sides and <img src="https://latex.codecogs.com/png.latex?A,%20B,%20C"> for opposite angles.</li>
<li><strong>Fact:</strong> He was the first to treat logarithms as functions and define them using the number <img src="https://latex.codecogs.com/png.latex?e">.</li>
<li><strong>Fact:</strong> He stayed at the <strong>St.&nbsp;Petersburg Academy</strong> twice, fleeing Berlin after falling out of favor with Frederick the Great.</li>
</ul>
</section>
</section>
<section id="max-planck-1858-1947" class="level1">
<h1>Max Planck (1858-1947)</h1>
<section id="biographical-professional-context" class="level2">
<h2 class="anchored" data-anchor-id="biographical-professional-context">1. Biographical &amp; Professional Context</h2>
<ul>
<li><strong>Origin:</strong> German theoretical physicist, born in <strong>Kiel</strong>.</li>
<li><strong>Education:</strong> Studied at Munich and Berlin under giants like <strong>Helmholtz</strong> and <strong>Kirchhoff</strong>.</li>
<li><strong>Career:</strong> Spent most of his career at the <strong>University of Berlin</strong>.</li>
<li><strong>Nobel Prize:</strong> Awarded the <strong>1918 Nobel Prize in Physics</strong> for the discovery of energy quanta.</li>
<li><strong>Historical Note:</strong> He was a “reluctant revolutionary.” Deeply conservative and trained in classical physics, he only proposed the quantum hypothesis as an “act of desperation” to fix a specific problem in thermodynamics.</li>
</ul>
</section>
<section id="the-core-discovery-black-body-radiation" class="level2">
<h2 class="anchored" data-anchor-id="the-core-discovery-black-body-radiation">2. The Core Discovery: Black-Body Radiation</h2>
<p>Before Planck, classical physics (the Rayleigh-Jeans Law) predicted the <strong>“Ultraviolet Catastrophe”</strong>—the impossible idea that an ideal radiator would emit infinite energy at short wavelengths (ultraviolet).</p>
<section id="plancks-law" class="level3">
<h3 class="anchored" data-anchor-id="plancks-law">Planck’s Law</h3>
<p>In 1900, Planck found a formula that perfectly matched experimental data by assuming energy is not continuous, but delivered in discrete “packets.” * <strong>The Formula:</strong> <img src="https://latex.codecogs.com/png.latex?E%20=%20h%20%5Cnu"> * <strong>Variables:</strong> * <img src="https://latex.codecogs.com/png.latex?E">: Energy of a single quantum (photon). * <img src="https://latex.codecogs.com/png.latex?h">: <strong>Planck’s Constant</strong> (<img src="https://latex.codecogs.com/png.latex?%5Capprox%206.626%20%5Ctimes%2010%5E%7B-34%7D%20%5Ctext%7B%20J%7D%5Ccdot%5Ctext%7Bs%7D">). This is a fundamental constant of nature. * <img src="https://latex.codecogs.com/png.latex?%5Cnu"> (or <img src="https://latex.codecogs.com/png.latex?f">): Frequency of the radiation.</p>
</section>
</section>
<section id="key-scientific-contributions" class="level2">
<h2 class="anchored" data-anchor-id="key-scientific-contributions">3. Key Scientific Contributions</h2>
<ul>
<li><strong>Quanta:</strong> Introduced the concept that energy is <strong>quantized</strong>. This ended the era of “Classical Physics” and began “Quantum Physics.”</li>
<li><strong>Thermodynamics:</strong> His early work focused on the <strong>Second Law of Thermodynamics</strong> and the concept of <strong>Entropy</strong> (<img src="https://latex.codecogs.com/png.latex?S">). He eventually linked entropy to probability using Boltzmann’s constant (<img src="https://latex.codecogs.com/png.latex?k">).</li>
<li><strong>Planck Units:</strong> He proposed a system of natural units based only on fundamental constants (<img src="https://latex.codecogs.com/png.latex?G,%20c,%20h">), known as Planck length, Planck time, etc.</li>
<li><strong>Support for Einstein:</strong> Planck was one of the first major scientists to recognize and champion Albert Einstein’s <strong>Special Theory of Relativity</strong> (1905).</li>
</ul>
</section>
<section id="philosophical-stance-later-life" class="level2">
<h2 class="anchored" data-anchor-id="philosophical-stance-later-life">4. Philosophical Stance &amp; Later Life</h2>
<ul>
<li><strong>Scientific Realism:</strong> Unlike later quantum physicists (like Bohr or Heisenberg), Planck struggled with the idea of “indeterminacy.” He believed in an objective, causal reality.</li>
<li><strong>The “Planck Principle”:</strong> He famously remarked that science doesn’t triumph by convincing its opponents, but rather because its opponents eventually die and a new generation grows up familiar with the new ideas.</li>
<li><strong>Personal Tragedy:</strong> His life was marked by sorrow; he lost his first wife and all four of his children from that marriage (including a son executed for a plot to assassinate Hitler in 1944).</li>
</ul>
</section>
<section id="fun-facts-1" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-1">5. Fun Facts</h2>
<ul>
<li><strong>Q:</strong> What specific problem did Planck solve?</li>
<li><strong>A:</strong> The Black-Body Radiation problem / Ultraviolet Catastrophe.</li>
<li><strong>Q:</strong> What is the “Quantum of Action”?</li>
<li><strong>A:</strong> Another name for <strong>Planck’s Constant (<img src="https://latex.codecogs.com/png.latex?h">)</strong>.</li>
<li><strong>Q:</strong> How did Planck view the nature of energy?</li>
<li><strong>A:</strong> As discrete “elements” or “quanta” rather than a continuous stream.</li>
<li><strong>Q:</strong> Which institution is named after him?</li>
<li><strong>A:</strong> The <strong>Max Planck Society</strong> (formerly the Kaiser Wilhelm Society), Germany’s premier research organization.</li>
</ul>
</section>
</section>
<section id="jacques-hadamard-1865-1963" class="level1">
<h1>Jacques Hadamard (1865-1963)</h1>
<section id="biographical-overview" class="level2">
<h2 class="anchored" data-anchor-id="biographical-overview">1. Biographical Overview</h2>
<ul>
<li><strong>Identity:</strong> A French mathematician often described as one of the last “universalists” because he contributed to almost every branch of mathematics.</li>
<li><strong>Education:</strong> Ranked <strong>1st</strong> in the entrance exams for both the École Polytechnique and the École Normale Supérieure (chose the latter).</li>
<li><strong>Career:</strong> Held prestigious chairs at the <strong>Collège de France</strong> and <strong>École Polytechnique</strong>.</li>
<li><strong>Personal Context:</strong> He was deeply affected by the <strong>Dreyfus Affair</strong> (Alfred Dreyfus was a relative by marriage), which turned him into a lifelong human rights activist. He lived to the age of 97, remaining mathematically active into his 90s.</li>
</ul>
</section>
<section id="number-theory-the-prime-number-theorem-1896" class="level2">
<h2 class="anchored" data-anchor-id="number-theory-the-prime-number-theorem-1896">2. Number Theory: The Prime Number Theorem (1896)</h2>
<p>This is arguably his most famous result. He proved the <strong>Prime Number Theorem (PNT)</strong> independently of Charles-Jean de la Vallée Poussin in the same year. * <strong>The Theorem:</strong> It describes the asymptotic distribution of prime numbers. * <strong>The Formula:</strong> If <img src="https://latex.codecogs.com/png.latex?%5Cpi(x)"> is the prime-counting function (the number of primes less than or equal to <img src="https://latex.codecogs.com/png.latex?x">), then: <img src="https://latex.codecogs.com/png.latex?%5Cpi(x)%20%5Csim%20%5Cfrac%7Bx%7D%7B%5Cln%20x%7D%20%5Ctext%7B%20as%20%7D%20x%20%5Cto%20%5Cinfty"> * <strong>Significance:</strong> He used complex analysis (specifically the Riemann zeta function <img src="https://latex.codecogs.com/png.latex?%5Czeta(s)">) to prove that <img src="https://latex.codecogs.com/png.latex?%5Czeta(s)"> has no zeros on the line <img src="https://latex.codecogs.com/png.latex?Re(s)%20=%201">.</p>
</section>
<section id="mathematical-physics-pdes" class="level2">
<h2 class="anchored" data-anchor-id="mathematical-physics-pdes">3. Mathematical Physics &amp; PDEs</h2>
<p>Hadamard laid the groundwork for how we solve physical problems using math. * <strong>Well-Posed Problems:</strong> He introduced the definition of a “well-posed” problem. A problem is well-posed if: 1. A solution exists. 2. The solution is unique. 3. The solution’s behavior changes continuously with the initial conditions (stability). * <strong>Method of Descent:</strong> A technical method he created for solving the wave equation in lower dimensions by “descending” from higher dimensions. * <strong>Cauchy Problem:</strong> He produced definitive work on the Cauchy problem for linear hyperbolic partial differential equations.</p>
</section>
<section id="other-key-contributions" class="level2">
<h2 class="anchored" data-anchor-id="other-key-contributions">4. Other Key Contributions</h2>
<ul>
<li><strong>Hadamard Matrix:</strong> A square matrix whose entries are either <img src="https://latex.codecogs.com/png.latex?+1"> or <img src="https://latex.codecogs.com/png.latex?-1"> and whose rows are mutually orthogonal. These are vital today in error-correcting codes and signal processing.</li>
<li><strong>Hadamard Inequality:</strong> A result regarding the maximum volume of a “box” in <img src="https://latex.codecogs.com/png.latex?n">-dimensions, or specifically, an upper bound on the determinant of a matrix: <img src="https://latex.codecogs.com/png.latex?%7C%5Cdet(A)%7C%20%5Cle%20%5Cprod_%7Bi=1%7D%5E%7Bn%7D%20%5C%7Cv_i%5C%7C"></li>
<li><strong>Functional Analysis:</strong> He was a pioneer in this field and actually <strong>coined the term “functional”</strong> to describe functions that take other functions as arguments.</li>
<li><strong>Psychology of Invention:</strong> Wrote a famous book, <em>The Psychology of Invention in the Mathematical Field</em>, where he argued that mathematical thought is often <strong>wordless</strong> and relies on mental images and the unconscious mind.</li>
</ul>
</section>
<section id="fun-facts-2" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-2">5. Fun Facts</h2>
<ul>
<li><strong>Major Achievement:</strong> Proving the Prime Number Theorem (<img src="https://latex.codecogs.com/png.latex?%5Cpi(x)%20%5Capprox%20x/%5Cln%20x">).</li>
<li><strong>Term Creator:</strong> He named the field/concept of a “functional.”</li>
<li><strong>Concept:</strong> The “Well-Posed Problem” (existence, uniqueness, stability).</li>
<li><strong>Constraint:</strong> His proof of the PNT required showing the Riemann Zeta function has no zeros where the real part is 1.</li>
</ul>
</section>
</section>
<section id="albert-einstein-1879-1955" class="level1">
<h1>Albert Einstein (1879-1955)</h1>
<section id="biographical-context" class="level2">
<h2 class="anchored" data-anchor-id="biographical-context">1. Biographical Context</h2>
<ul>
<li><strong>Origin:</strong> German-born theoretical physicist (Ulm, Germany).</li>
<li><strong>Early Career:</strong> Famously worked as a technical assistant at the <strong>Swiss Patent Office</strong> in Bern, where he developed many of his greatest ideas during his “spare time.”</li>
<li><strong>Global Impact:</strong> Moved to the <strong>Institute for Advanced Study</strong> in Princeton, NJ, in 1933 after fleeing Nazi Germany.</li>
<li><strong>Nobel Prize (1921):</strong> Awarded for his discovery of the law of the <strong>photoelectric effect</strong>, <em>not</em> for Relativity (which was still considered controversial by the Nobel committee at the time).</li>
</ul>
</section>
<section id="the-annus-mirabilis-1905" class="level2">
<h2 class="anchored" data-anchor-id="the-annus-mirabilis-1905">2. The “Annus Mirabilis” (1905)</h2>
<p>While still a patent clerk, Einstein published four papers in <em>Annalen der Physik</em> that revolutionized science: 1. <strong>Photoelectric Effect:</strong> Proposed that light consists of discrete “quanta” (photons). This provided the first solid evidence for quantum theory. 2. <strong>Brownian Motion:</strong> Provided empirical evidence for the existence of atoms by explaining the random motion of particles in a fluid. 3. <strong>Special Relativity:</strong> Introduced the idea that the laws of physics are the same for all non-accelerating observers and that the speed of light is constant. 4. <strong>Mass-Energy Equivalence:</strong> Derived the most famous equation in history: <img src="https://latex.codecogs.com/png.latex?E%20=%20mc%5E2"></p>
</section>
<section id="general-relativity-1915" class="level2">
<h2 class="anchored" data-anchor-id="general-relativity-1915">3. General Relativity (1915)</h2>
<p>Einstein expanded his theory to include acceleration and gravity. * <strong>The Concept:</strong> Gravity is not a “force” (as Newton thought) but a <strong>curvature of spacetime</strong> caused by mass and energy. * <strong>The Field Equations:</strong> <img src="https://latex.codecogs.com/png.latex?G_%7B%5Cmu%5Cnu%7D%20+%20%5CLambda%20g_%7B%5Cmu%5Cnu%7D%20=%20%5Cfrac%7B8%5Cpi%20G%7D%7Bc%5E4%7D%20T_%7B%5Cmu%5Cnu%7D"> * <strong>Experimental Proof:</strong> Confirmed in 1919 by <strong>Arthur Eddington</strong> during a solar eclipse, showing that gravity bends starlight passing near the sun.</p>
</section>
<section id="key-concepts-terms" class="level2">
<h2 class="anchored" data-anchor-id="key-concepts-terms">4. Key Concepts &amp; Terms</h2>
<ul>
<li><strong>Postulate of Special Relativity:</strong> The speed of light (<img src="https://latex.codecogs.com/png.latex?c">) in a vacuum is the same for all observers, regardless of their motion.</li>
<li><strong>Time Dilation:</strong> Time moves slower for an object in motion relative to a stationary observer.</li>
<li><strong>Length Contraction:</strong> Objects in motion appear shorter in the direction of travel to a stationary observer.</li>
<li><strong>Equivalence Principle:</strong> The idea that the local effects of gravity are indistinguishable from the effects of acceleration.</li>
<li><strong>Cosmological Constant (<img src="https://latex.codecogs.com/png.latex?%5CLambda">):</strong> Originally added to his equations to allow for a static universe; he later called it his “biggest blunder” after Hubble discovered the universe is expanding.</li>
</ul>
</section>
<section id="fun-facts-3" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-3">5. Fun Facts</h2>
<ul>
<li><strong>Q: Why did Einstein win the Nobel Prize?</strong></li>
<li><strong>A:</strong> For the Photoelectric Effect (proving light behaves as a particle).</li>
<li><strong>Q: What is the significance of <img src="https://latex.codecogs.com/png.latex?E=mc%5E2">?</strong></li>
<li><strong>A:</strong> It shows that mass and energy are interchangeable; a small amount of mass can be converted into a huge amount of energy.</li>
<li><strong>Q: What is the “EPR Paradox”?</strong></li>
<li><strong>A:</strong> A paper written with Podolsky and Rosen challenging the “spooky action at a distance” (quantum entanglement) in Copenhagen-style quantum mechanics.</li>
<li><strong>Q: Did Einstein believe in a deterministic universe?</strong></li>
<li><strong>A:</strong> Yes. He famously said, “God does not play dice with the universe,” expressing his skepticism of the probabilistic nature of quantum mechanics.</li>
</ul>
</section>
</section>
<section id="max-born-1882-1970" class="level1">
<h1>Max Born (1882-1970)</h1>
<section id="biographical-academic-context" class="level2">
<h2 class="anchored" data-anchor-id="biographical-academic-context">1. Biographical &amp; Academic Context</h2>
<ul>
<li><strong>Origin:</strong> German physicist and mathematician born in <strong>Breslau</strong> (now Poland).</li>
<li><strong>Education:</strong> Studied at several universities, but his time at <strong>Göttingen</strong> under Hilbert and Minkowski was most influential.</li>
<li><strong>Academic Hub:</strong> He made the <strong>University of Göttingen</strong> the world’s premier center for theoretical physics in the 1920s.</li>
<li><strong>Exile:</strong> Being of Jewish descent, he was forced to leave Germany in 1933, eventually becoming the Tait Professor of Natural Philosophy at the <strong>University of Edinburgh</strong>.</li>
<li><strong>Nobel Prize (1954):</strong> Awarded “for his fundamental research in quantum mechanics, especially for his statistical interpretation of the wavefunction.”</li>
</ul>
</section>
<section id="the-statistical-interpretation-the-born-rule" class="level2">
<h2 class="anchored" data-anchor-id="the-statistical-interpretation-the-born-rule">2. The Statistical Interpretation (The Born Rule)</h2>
<p>This is his most critical contribution to science and a common exam topic. * <strong>The Problem:</strong> Schrödinger’s wave equation described a wave (<img src="https://latex.codecogs.com/png.latex?%5Cpsi">), but it wasn’t clear what that wave physically represented. * <strong>The Solution:</strong> Born proposed that the square of the magnitude of the wavefunction gives the <strong>probability density</strong>. * <strong>The Formula:</strong> The probability of finding a particle at a point <img src="https://latex.codecogs.com/png.latex?(x,%20y,%20z)"> is: <img src="https://latex.codecogs.com/png.latex?P(x,%20y,%20z)%20=%20%7C%5Cpsi(x,%20y,%20z)%7C%5E2"> * <strong>Significance:</strong> This introduced <strong>probability</strong> into the heart of physics, replacing the absolute certainty (determinism) of Newtonian mechanics.</p>
</section>
<section id="matrix-mechanics" class="level2">
<h2 class="anchored" data-anchor-id="matrix-mechanics">3. Matrix Mechanics</h2>
<ul>
<li><strong>Collaboration:</strong> Worked closely with his assistant <strong>Werner Heisenberg</strong> and student <strong>Pascual Jordan</strong>.</li>
<li><strong>Contribution:</strong> When Heisenberg developed a strange new symbolic logic for transitions in atoms, Born recognized it as <strong>Matrix Algebra</strong> (which was then obscure to most physicists).</li>
<li><strong>Result:</strong> They published the “Three-Man Paper” (<em>Dreimännerarbeit</em>), which provided the first complete mathematical formulation of quantum mechanics.</li>
<li><strong>Commutation Relation:</strong> He helped derive the fundamental link between position (<img src="https://latex.codecogs.com/png.latex?p">) and momentum (<img src="https://latex.codecogs.com/png.latex?q">): <img src="https://latex.codecogs.com/png.latex?pq%20-%20qp%20=%20%5Cfrac%7Bh%7D%7B2%5Cpi%20i%7DI"></li>
</ul>
</section>
<section id="solid-state-physics-optics" class="level2">
<h2 class="anchored" data-anchor-id="solid-state-physics-optics">4. Solid State Physics &amp; Optics</h2>
<ul>
<li><strong>Born-Oppenheimer Approximation:</strong> A foundational technique in molecular physics and quantum chemistry that allows for the separation of nuclear and electronic motion.</li>
<li><strong>Crystal Dynamics:</strong> Developed the theory of lattice dynamics, explaining how atoms in a solid vibrate.</li>
<li><strong>Principles of Optics:</strong> Wrote one of the most famous textbooks on the subject (<em>Optik</em>), which is still a standard reference.</li>
</ul>
</section>
<section id="fun-facts-4" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-4">5. Fun Facts</h2>
<ul>
<li><strong>Q: What is the “Born Rule”?</strong></li>
<li><strong>A:</strong> The rule stating that <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%7C%5E2"> represents the probability density of finding a particle.</li>
<li><strong>Q: Who were some of his famous students?</strong></li>
<li><strong>A:</strong> Heisenberg, Oppenheimer, Fermi, Pauli, and Maria Goeppert-Mayer.</li>
<li><strong>Q: How did he differ from Einstein on Quantum Mechanics?</strong></li>
<li><strong>A:</strong> Born championed the probabilistic nature of the universe; Einstein famously disagreed, leading to their lifelong “God does not play dice” debate (despite remaining close friends).</li>
<li><strong>Q: What was his stance on nuclear weapons?</strong></li>
<li><strong>A:</strong> Like many of his peers, he was deeply concerned with the social responsibility of scientists and was a signer of the <strong>Russell-Einstein Manifesto</strong>.</li>
</ul>
</section>
</section>
<section id="niels-bohr-1885-1962" class="level1">
<h1>Niels Bohr (1885-1962)</h1>
<section id="biographical-professional-context-1" class="level2">
<h2 class="anchored" data-anchor-id="biographical-professional-context-1">1. Biographical &amp; Professional Context</h2>
<ul>
<li><strong>Origin:</strong> Danish physicist born in <strong>Copenhagen</strong>.</li>
<li><strong>Academic Hub:</strong> Founded the <strong>Institute of Theoretical Physics</strong> in Copenhagen (now the Niels Bohr Institute), which became the epicenter for quantum research in the 1920s and 30s.</li>
<li><strong>Nobel Prize (1922):</strong> Awarded for his investigation of the structure of atoms and the radiation emanating from them.</li>
<li><strong>World War II:</strong> Bohr assisted in the escape of Jewish scientists from Nazi Germany and later fled to Sweden, the UK, and the US (joining the Manhattan Project under the pseudonym “Nicholas Baker”).</li>
</ul>
</section>
<section id="the-bohr-model-of-the-atom-1913" class="level2">
<h2 class="anchored" data-anchor-id="the-bohr-model-of-the-atom-1913">2. The Bohr Model of the Atom (1913)</h2>
<p>Bohr revolutionized the planetary model of the atom by introducing quantization. * <strong>Key Postulates:</strong> 1. Electrons orbit the nucleus in specific <strong>stationary states</strong> (orbits) without radiating energy. 2. Electrons can only exist in orbits where their <strong>angular momentum (<img src="https://latex.codecogs.com/png.latex?L">)</strong> is an integer multiple of <img src="https://latex.codecogs.com/png.latex?%5Chbar">: <img src="https://latex.codecogs.com/png.latex?L%20=%20n%5Chbar%20=%20%5Cfrac%7Bnh%7D%7B2%5Cpi%7D"> 3. Radiation is emitted or absorbed only when an electron “jumps” from one orbit to another. * <strong>Energy Transition Formula:</strong> The energy of the emitted photon (<img src="https://latex.codecogs.com/png.latex?%5CDelta%20E">) corresponds to the difference between energy levels: <img src="https://latex.codecogs.com/png.latex?%5CDelta%20E%20=%20E_%7Bfinal%7D%20-%20E_%7Binitial%7D%20=%20h%5Cnu"></p>
</section>
<section id="the-correspondence-principle" class="level2">
<h2 class="anchored" data-anchor-id="the-correspondence-principle">3. The Correspondence Principle</h2>
<ul>
<li><strong>The Concept:</strong> Bohr argued that quantum mechanics must transition into classical physics when dealing with large systems or high quantum numbers (<img src="https://latex.codecogs.com/png.latex?n%20%5Cto%20%5Cinfty">).</li>
<li><strong>Significance:</strong> This served as a vital bridge for physicists to develop quantum theory while ensuring it remained consistent with established classical laws in the macroscopic limit.</li>
</ul>
</section>
<section id="the-principle-of-complementarity" class="level2">
<h2 class="anchored" data-anchor-id="the-principle-of-complementarity">4. The Principle of Complementarity</h2>
<p>This is the philosophical heart of the <strong>Copenhagen Interpretation</strong>. * <strong>The Idea:</strong> Items can have “complementary” properties that cannot be observed or measured simultaneously (like the wave-particle duality of light/electrons). * <strong>Bohr’s View:</strong> To get a full understanding of a physical object, both perspectives are necessary, even though they are mutually exclusive in a single experiment. * <strong>Legacy:</strong> This led to a famous lifelong debate with Albert Einstein, who remained skeptical of the probabilistic nature of this interpretation.</p>
</section>
<section id="fun-facts-5" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-5">5. Fun Facts</h2>
<ul>
<li><strong>Q: What was the main flaw Bohr fixed in the Rutherford model?</strong></li>
<li><strong>A:</strong> He explained why electrons don’t spiral into the nucleus by quantizing their orbits.</li>
<li><strong>Q: What is the “Copenhagen Interpretation”?</strong></li>
<li><strong>A:</strong> The standard view of quantum mechanics (developed by Bohr and Heisenberg) asserting that physical systems don’t have definite properties until they are measured.</li>
<li><strong>Q: What element is named after him?</strong></li>
<li><strong>A:</strong> <strong>Bohrium (element 107)</strong>.</li>
<li><strong>Q: What was his famous motto/coat of arms symbol?</strong></li>
<li><strong>A:</strong> The <strong>Yin and Yang</strong> symbol, representing his Principle of Complementarity (“Contraria sunt complementa”).</li>
</ul>
</section>
</section>
<section id="erwin-schrödinger-1887-1961" class="level1">
<h1>Erwin Schrödinger (1887-1961)</h1>
<section id="biographical-historical-context" class="level2">
<h2 class="anchored" data-anchor-id="biographical-historical-context">1. Biographical &amp; Historical Context</h2>
<ul>
<li><strong>Origin:</strong> Austrian theoretical physicist born in <strong>Vienna</strong>.</li>
<li><strong>Academic Path:</strong> Held the prestigious chair of theoretical physics at the <strong>University of Berlin</strong> (succeeding Max Planck) before leaving Germany in 1933 due to his opposition to Nazism.</li>
<li><strong>Nobel Prize (1933):</strong> Shared with <strong>Paul Dirac</strong> for the discovery of new productive forms of atomic theory.</li>
<li><strong>Later Life:</strong> Spent many years at the <strong>Dublin Institute for Advanced Studies</strong>, where he wrote on physics, biology, and philosophy.</li>
</ul>
</section>
<section id="the-schrödinger-equation-1926" class="level2">
<h2 class="anchored" data-anchor-id="the-schrödinger-equation-1926">2. The Schrödinger Equation (1926)</h2>
<p>This is his most monumental contribution. It describes how the quantum state of a physical system changes with time. * <strong>The Wave Function (<img src="https://latex.codecogs.com/png.latex?%5Cpsi">):</strong> Unlike Heisenberg’s “Matrix Mechanics,” Schrödinger used a wave equation approach, which was more familiar to physicists trained in classical acoustics and optics. * <strong>The Time-Dependent Equation:</strong> <img src="https://latex.codecogs.com/png.latex?i%5Chbar%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20t%7D%20%5CPsi(%5Cmathbf%7Br%7D,t)%20=%20%5Chat%7BH%7D%20%5CPsi(%5Cmathbf%7Br%7D,t)"> * <strong>The Hamiltonian (<img src="https://latex.codecogs.com/png.latex?%5Chat%7BH%7D">):</strong> This operator represents the total energy of the system (kinetic + potential). * <strong>Significance:</strong> This equation is to quantum mechanics what <img src="https://latex.codecogs.com/png.latex?F=ma"> is to classical mechanics.</p>
</section>
<section id="wave-mechanics-vs.-matrix-mechanics" class="level2">
<h2 class="anchored" data-anchor-id="wave-mechanics-vs.-matrix-mechanics">3. Wave Mechanics vs.&nbsp;Matrix Mechanics</h2>
<ul>
<li><strong>Unity:</strong> Initially, Heisenberg’s and Schrödinger’s theories seemed like competing rivals.</li>
<li><strong>Equivalence:</strong> Schrödinger proved that his “Wave Mechanics” and Heisenberg’s “Matrix Mechanics” were mathematically equivalent—they were just two different “languages” describing the same underlying reality.</li>
</ul>
</section>
<section id="famous-thought-experiments-concepts" class="level2">
<h2 class="anchored" data-anchor-id="famous-thought-experiments-concepts">4. Famous Thought Experiments &amp; Concepts</h2>
<ul>
<li><strong>Schrödinger’s Cat:</strong> A paradox intended to critique the <strong>Copenhagen Interpretation</strong>. It illustrates the problem of <strong>superposition</strong> (the cat being “dead and alive”) and how quantum effects scale up to the macroscopic world.</li>
<li><strong>Quantum Tunneling:</strong> His equations allowed for the possibility of particles “tunneling” through energy barriers that they classically shouldn’t be able to cross.</li>
<li><strong>“What is Life?” (1944):</strong> He wrote an influential book exploring the physical basis of genetics. He proposed the idea of an <strong>“aperiodic crystal”</strong> that stored genetic information, which directly inspired <strong>Watson and Crick</strong> in their discovery of DNA.</li>
</ul>
</section>
<section id="fun-facts-6" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-6">5. Fun Facts</h2>
<ul>
<li><strong>Q: What was Schrödinger’s primary tool for describing the atom?</strong></li>
<li><strong>A:</strong> Differential equations (Wave Mechanics).</li>
<li><strong>Q: Did Schrödinger like the probabilistic “Born Rule” interpretation?</strong></li>
<li><strong>A:</strong> Not initially. Like Einstein, he was uncomfortable with the idea of “probability waves” and preferred a more literal, continuous wave interpretation.</li>
<li><strong>Q: What is a “stationary state” in his theory?</strong></li>
<li><strong>A:</strong> An energy level where the probability density <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%7C%5E2"> does not change over time.</li>
<li><strong>Q: What was his contribution to biology?</strong></li>
<li><strong>A:</strong> His book <em>What is Life?</em> suggested that genetic material must be a complex molecule, paving the way for molecular biology.</li>
</ul>
</section>
</section>
<section id="louis-de-broglie-1892-1987" class="level1">
<h1>Louis de Broglie (1892-1987)</h1>
<section id="biographical-professional-context-2" class="level2">
<h2 class="anchored" data-anchor-id="biographical-professional-context-2">1. Biographical &amp; Professional Context</h2>
<ul>
<li><strong>Origin:</strong> French physicist born in <strong>Dieppe</strong> into a noble family (he later became the 7th Duc de Broglie).</li>
<li><strong>Education:</strong> Originally studied <strong>History</strong> at the Sorbonne before switching to Physics after serving as a radio operator in World War I (at the Eiffel Tower).</li>
<li><strong>The “Thesis”:</strong> His most famous work was his 1924 doctoral thesis, <em>Recherches sur la théorie des quanta</em>. It was so revolutionary that his examiners consulted <strong>Einstein</strong>, who immediately recognized its brilliance.</li>
<li><strong>Nobel Prize (1929):</strong> Awarded for his discovery of the wave nature of electrons.</li>
</ul>
</section>
<section id="wave-particle-duality-of-matter" class="level2">
<h2 class="anchored" data-anchor-id="wave-particle-duality-of-matter">2. Wave-Particle Duality of Matter</h2>
<p>Before de Broglie, light was known to have both wave and particle properties (Photoelectric Effect). De Broglie proposed the inverse: that <strong>matter</strong> (particles) must also have <strong>wave</strong> properties.</p>
<section id="the-de-broglie-relation" class="level3">
<h3 class="anchored" data-anchor-id="the-de-broglie-relation">The De Broglie Relation</h3>
<p>This formula relates the momentum of a particle to its wavelength. * <strong>The Formula:</strong> <img src="https://latex.codecogs.com/png.latex?%5Clambda%20=%20%5Cfrac%7Bh%7D%7Bp%7D%20=%20%5Cfrac%7Bh%7D%7Bmv%7D"> * <strong>Variables:</strong> * <img src="https://latex.codecogs.com/png.latex?%5Clambda">: De Broglie wavelength. * <img src="https://latex.codecogs.com/png.latex?h">: Planck’s constant. * <img src="https://latex.codecogs.com/png.latex?p">: Momentum (<img src="https://latex.codecogs.com/png.latex?mass%20%5Ctimes%20velocity">).</p>
</section>
</section>
<section id="explaining-bohrs-atom" class="level2">
<h2 class="anchored" data-anchor-id="explaining-bohrs-atom">3. Explaining Bohr’s Atom</h2>
<p>One of de Broglie’s greatest achievements was providing a physical reason for <strong>Bohr’s quantized orbits</strong>. * <strong>Standing Waves:</strong> He proposed that an electron can only exist in an orbit where its wave doesn’t cancel itself out. * <strong>Quantization Condition:</strong> The circumference of the electron’s orbit must be an integer multiple (<img src="https://latex.codecogs.com/png.latex?n">) of its wavelength: <img src="https://latex.codecogs.com/png.latex?2%5Cpi%20r%20=%20n%5Clambda"> * <strong>Significance:</strong> This turned Bohr’s “ad hoc” rule for angular momentum into a logical consequence of wave mechanics.</p>
</section>
<section id="experimental-confirmation" class="level2">
<h2 class="anchored" data-anchor-id="experimental-confirmation">4. Experimental Confirmation</h2>
<ul>
<li><strong>Davisson-Germer Experiment (1927):</strong> Electrons were fired at a nickel crystal and produced a <strong>diffraction pattern</strong>. Since diffraction is a wave phenomenon, this proved de Broglie’s hypothesis that particles behave like waves.</li>
<li><strong>Legacy:</strong> This discovery was the direct inspiration for <strong>Schrödinger</strong> to develop his wave equation (<img src="https://latex.codecogs.com/png.latex?H%5Cpsi%20=%20E%5Cpsi">).</li>
</ul>
</section>
<section id="later-concepts-pilot-wave-theory" class="level2">
<h2 class="anchored" data-anchor-id="later-concepts-pilot-wave-theory">5. Later Concepts: Pilot Wave Theory</h2>
<ul>
<li><strong>Non-Copenhagen View:</strong> De Broglie initially proposed the <strong>Pilot Wave Theory</strong> (or de Broglie–Bohm theory).</li>
<li><strong>The Idea:</strong> Particles are “real” and are “guided” by a physical wave (a “pilot wave”).</li>
<li><strong>Outcome:</strong> He eventually abandoned this due to criticism from the Copenhagen school (Bohr/Heisenberg), but it remains a significant alternative interpretation of quantum mechanics today.</li>
</ul>
</section>
<section id="fun-facts-7" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-7">6. Fun Facts</h2>
<ul>
<li><strong>Q: What was de Broglie’s central hypothesis?</strong></li>
<li><strong>A:</strong> That all matter exhibits wave-particle duality (Matter Waves).</li>
<li><strong>Q: How does wavelength relate to mass?</strong></li>
<li><strong>A:</strong> Inversely. As mass (<img src="https://latex.codecogs.com/png.latex?m">) increases, the wavelength (<img src="https://latex.codecogs.com/png.latex?%5Clambda">) becomes so small it is undetectable (which is why humans don’t “diffract” through doors).</li>
<li><strong>Q: Who confirmed his theory experimentally?</strong></li>
<li><strong>A:</strong> Davisson and Germer (via electron diffraction).</li>
<li><strong>Q: Which famous equation did his work inspire?</strong></li>
<li><strong>A:</strong> The Schrödinger Equation.</li>
</ul>
</section>
</section>
<section id="wolfgang-pauli-1900-1958" class="level1">
<h1>Wolfgang Pauli (1900-1958)</h1>
<section id="biographical-intellectual-context" class="level2">
<h2 class="anchored" data-anchor-id="biographical-intellectual-context">1. Biographical &amp; Intellectual Context</h2>
<ul>
<li><strong>Origin:</strong> Austrian theoretical physicist born in <strong>Vienna</strong>.</li>
<li><strong>Prodigy:</strong> At age 21, he wrote a 200-page review of <strong>General Relativity</strong> that even Einstein praised for its depth and clarity.</li>
<li><strong>Reputation:</strong> Known as the “Whip of God” or the “Conscience of Physics” because of his devastatingly sharp critiques of incorrect theories (famously coining the phrase <strong>“Not even wrong”</strong>).</li>
<li><strong>Nobel Prize (1945):</strong> Nominated by Einstein and awarded for the discovery of the Exclusion Principle.</li>
</ul>
</section>
<section id="the-pauli-exclusion-principle-1925" class="level2">
<h2 class="anchored" data-anchor-id="the-pauli-exclusion-principle-1925">2. The Pauli Exclusion Principle (1925)</h2>
<p>This is his most fundamental contribution to chemistry and physics. It explains the structure of the periodic table and the stability of matter. * <strong>The Principle:</strong> No two <strong>fermions</strong> (electrons, protons, neutrons) in a system can occupy the identical quantum state simultaneously. * <strong>Quantum Numbers:</strong> An electron in an atom is defined by four quantum numbers: 1. <img src="https://latex.codecogs.com/png.latex?n"> (Principal) 2. <img src="https://latex.codecogs.com/png.latex?l"> (Angular momentum) 3. <img src="https://latex.codecogs.com/png.latex?m_l"> (Magnetic) 4. <img src="https://latex.codecogs.com/png.latex?s"> (Spin) — <em>Pauli realized a fourth degree of freedom was needed.</em> * <strong>Significance:</strong> This principle prevents atoms from collapsing and explains why electrons fill shells in a specific order.</p>
</section>
<section id="the-prediction-of-the-neutrino-1930" class="level2">
<h2 class="anchored" data-anchor-id="the-prediction-of-the-neutrino-1930">3. The Prediction of the Neutrino (1930)</h2>
<p>Pauli solved a crisis in nuclear physics regarding <strong>Beta Decay</strong>. * <strong>The Problem:</strong> Experiments showed that energy and momentum appeared to be “lost” during beta decay, threatening the Law of Conservation of Energy. * <strong>The Solution:</strong> Pauli proposed a “desperate remedy”—a neutral, nearly massless particle that carried away the missing energy. * <strong>The Particle:</strong> Later named the <strong>Neutrino</strong> (<img src="https://latex.codecogs.com/png.latex?%5Cnu">) by Enrico Fermi. It wasn’t experimentally detected until 1956, 26 years after Pauli’s prediction.</p>
</section>
<section id="pauli-spin-matrices" class="level2">
<h2 class="anchored" data-anchor-id="pauli-spin-matrices">4. Pauli Spin Matrices</h2>
<p>Pauli developed the mathematical framework for describing the <strong>spin</strong> of particles with half-integer angular momentum. * <strong>The Matrices (<img src="https://latex.codecogs.com/png.latex?%5Csigma">):</strong> <img src="https://latex.codecogs.com/png.latex?%5Csigma_x%20=%20%5Cbegin%7Bpmatrix%7D%200%20&amp;%201%20%5C%5C%201%20&amp;%200%20%5Cend%7Bpmatrix%7D,%20%5Cquad%20%5Csigma_y%20=%20%5Cbegin%7Bpmatrix%7D%200%20&amp;%20-i%20%5C%5C%20i%20&amp;%200%20%5Cend%7Bpmatrix%7D,%20%5Cquad%20%5Csigma_z%20=%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%200%20%5C%5C%200%20&amp;%20-1%20%5Cend%7Bpmatrix%7D"> * <strong>Quantum Computing Link:</strong> These matrices are the basis for the <strong>X, Y, and Z gates</strong> used in quantum circuits today.</p>
</section>
<section id="the-pauli-effect-anecdotal" class="level2">
<h2 class="anchored" data-anchor-id="the-pauli-effect-anecdotal">5. The “Pauli Effect” (Anecdotal)</h2>
<ul>
<li><strong>The Myth:</strong> It was jokingly said that sensitive experimental equipment would break or explode simply by Pauli entering the room.</li>
<li><strong>The Legend:</strong> Fellow physicists (like Otto Stern) famously banned Pauli from their laboratories to protect their experiments.</li>
</ul>
</section>
<section id="fun-facts-8" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-8">6. Fun Facts</h2>
<ul>
<li><strong>Q: What particle did Pauli predict to save the Law of Conservation of Energy?</strong></li>
<li><strong>A:</strong> The Neutrino.</li>
<li><strong>Q: What class of particles obeys the Exclusion Principle?</strong></li>
<li><strong>A:</strong> Fermions (particles with half-integer spin).</li>
<li><strong>Q: What is the “Spin-Statistics Theorem”?</strong></li>
<li><strong>A:</strong> A fundamental result (refined by Pauli) linking a particle’s spin to the type of quantum statistics it obeys (Fermi-Dirac vs.&nbsp;Bose-Einstein).</li>
<li><strong>Q: Which quantum number did Pauli effectively introduce?</strong></li>
<li><strong>A:</strong> The fourth quantum number, representing electron spin (<img src="https://latex.codecogs.com/png.latex?s">).</li>
</ul>
</section>
</section>
<section id="werner-heisenberg-1901-1976" class="level1">
<h1>Werner Heisenberg (1901-1976)</h1>
<section id="biographical-professional-context-3" class="level2">
<h2 class="anchored" data-anchor-id="biographical-professional-context-3">1. Biographical &amp; Professional Context</h2>
<ul>
<li><strong>Origin:</strong> German theoretical physicist born in <strong>Würzburg</strong>.</li>
<li><strong>Education:</strong> Studied under <strong>Arnold Sommerfeld</strong> in Munich and worked as an assistant to <strong>Max Born</strong> in Göttingen and <strong>Niels Bohr</strong> in Copenhagen.</li>
<li><strong>Nobel Prize (1932):</strong> Awarded for the creation of quantum mechanics, the application of which has, inter alia, led to the discovery of the allotropic forms of hydrogen.</li>
<li><strong>WWII Role:</strong> Led the German nuclear energy project (the Uranium Club). His role remains a subject of intense historical debate regarding whether he intentionally stalled the project or simply lacked the resources.</li>
</ul>
</section>
<section id="matrix-mechanics-1925" class="level2">
<h2 class="anchored" data-anchor-id="matrix-mechanics-1925">2. Matrix Mechanics (1925)</h2>
<p>Heisenberg rejected the idea of “orbits” because they couldn’t be observed. He argued physics should only deal with <strong>observables</strong> (like the frequencies of light emitted by atoms). * <strong>Innovation:</strong> He developed a system of non-commutative algebra to describe these observables. * <strong>The Collaboration:</strong> Max Born recognized this algebra as <strong>Matrix Mechanics</strong>. * <strong>The Fundamental Commutation Relation:</strong> <img src="https://latex.codecogs.com/png.latex?%5Bp,%20q%5D%20=%20pq%20-%20qp%20=%20-i%5Chbar"> * <strong>Significance:</strong> This showed that in quantum mechanics, the order in which you measure things (like position <img src="https://latex.codecogs.com/png.latex?q"> and momentum <img src="https://latex.codecogs.com/png.latex?p">) matters.</p>
</section>
<section id="the-uncertainty-principle-1927" class="level2">
<h2 class="anchored" data-anchor-id="the-uncertainty-principle-1927">3. The Uncertainty Principle (1927)</h2>
<p>This is his most famous contribution. It sets a fundamental limit on how precisely we can know certain pairs of physical properties. * <strong>The Principle:</strong> The more precisely the position of a particle is determined, the less precisely its momentum can be known, and vice versa. * <strong>The Formula:</strong> <img src="https://latex.codecogs.com/png.latex?%5CDelta%20x%20%5Ccdot%20%5CDelta%20p%20%5Cge%20%5Cfrac%7B%5Chbar%7D%7B2%7D"> * <strong>Variables:</strong> * <img src="https://latex.codecogs.com/png.latex?%5CDelta%20x">: Uncertainty in position. * <img src="https://latex.codecogs.com/png.latex?%5CDelta%20p">: Uncertainty in momentum. * <strong>Philosophical Impact:</strong> It destroyed the “Clockwork Universe” (Determinism). If we cannot know the present state of a particle perfectly, we cannot predict its future perfectly.</p>
</section>
<section id="the-copenhagen-interpretation" class="level2">
<h2 class="anchored" data-anchor-id="the-copenhagen-interpretation">4. The Copenhagen Interpretation</h2>
<p>Along with <strong>Niels Bohr</strong>, Heisenberg formulated the standard way of understanding quantum mechanics. * <strong>Key Idea:</strong> A quantum system does not have definite properties until it is measured. * <strong>Wavefunction Collapse:</strong> The act of measurement “forces” the system into a specific state.</p>
</section>
<section id="later-scientific-work" class="level2">
<h2 class="anchored" data-anchor-id="later-scientific-work">5. Later Scientific Work</h2>
<ul>
<li><strong>Isospin:</strong> Introduced the concept of isospin to explain the symmetry between protons and neutrons in the nucleus.</li>
<li><strong>Ferromagnetism:</strong> Provided a quantum mechanical explanation for why certain materials become magnetic (the exchange interaction).</li>
<li><strong>S-matrix Theory:</strong> Attempted to describe particle interactions without needing a detailed underlying field theory.</li>
</ul>
</section>
<section id="fun-facts-9" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-9">6. Fun Facts</h2>
<ul>
<li><strong>Q: What was Heisenberg’s “observables only” philosophy?</strong></li>
<li><strong>A:</strong> He believed physics should only model things that can be measured (spectra), not unobservable things like “electron paths.”</li>
<li><strong>Q: How did his theory differ from Schrödinger’s?</strong></li>
<li><strong>A:</strong> Heisenberg used discrete matrices (Matrix Mechanics); Schrödinger used continuous waves (Wave Mechanics).</li>
<li><strong>Q: What is the “gamma-ray microscope” thought experiment?</strong></li>
<li><strong>A:</strong> A mental exercise Heisenberg used to illustrate the Uncertainty Principle: to “see” an electron, you must hit it with a high-energy photon, which inevitably changes the electron’s momentum.</li>
<li><strong>Q: What is the significance of the “hbar” (<img src="https://latex.codecogs.com/png.latex?%5Chbar">)?</strong></li>
<li><strong>A:</strong> It is the reduced Planck constant (<img src="https://latex.codecogs.com/png.latex?h/2%5Cpi">), the fundamental scale of the quantum world.</li>
</ul>
</section>
</section>
<section id="paul-dirac-1902-1984" class="level1">
<h1>Paul Dirac (1902-1984)</h1>
<section id="biographical-professional-context-4" class="level2">
<h2 class="anchored" data-anchor-id="biographical-professional-context-4">1. Biographical &amp; Professional Context</h2>
<ul>
<li><strong>Origin:</strong> British theoretical physicist born in <strong>Bristol</strong>.</li>
<li><strong>Education:</strong> Originally trained as an <strong>Electrical Engineer</strong>, which influenced his “mathematical beauty” approach to physics.</li>
<li><strong>Character:</strong> Famous for his extreme silence and literal-mindedness (colleagues jokingly defined a “Dirac” as the unit of one word per hour).</li>
<li><strong>Nobel Prize (1933):</strong> Shared with <strong>Erwin Schrödinger</strong> for the discovery of new productive forms of atomic theory.</li>
<li><strong>Legacy:</strong> Held the <strong>Lucasian Chair of Mathematics</strong> at Cambridge (the same chair held by Newton and later Hawking).</li>
</ul>
</section>
<section id="the-dirac-equation-1928" class="level2">
<h2 class="anchored" data-anchor-id="the-dirac-equation-1928">2. The Dirac Equation (1928)</h2>
<p>This is his most monumental achievement. He sought an equation for the electron that was consistent with <strong>Special Relativity</strong>. * <strong>The Equation:</strong> <img src="https://latex.codecogs.com/png.latex?(i%5Cgamma%5E%5Cmu%20%5Cpartial_%5Cmu%20-%20m)%20%5Cpsi%20=%200"> * <strong>Key Components:</strong> * <img src="https://latex.codecogs.com/png.latex?%5Cpsi">: A four-component <strong>spinor</strong> (rather than a simple wave function). * <img src="https://latex.codecogs.com/png.latex?%5Cgamma%5E%5Cmu">: The <strong>Dirac Matrices</strong> (4x4 matrices). * <strong>Major Successes:</strong> 1. It naturally predicted the <strong>electron spin</strong> (<img src="https://latex.codecogs.com/png.latex?s%20=%201/2">) as a mathematical necessity of relativity. 2. It gave the correct magnetic moment of the electron.</p>
</section>
<section id="prediction-of-antimatter" class="level2">
<h2 class="anchored" data-anchor-id="prediction-of-antimatter">3. Prediction of Antimatter</h2>
<p>The Dirac Equation had a “problem”: it allowed for <strong>negative energy states</strong>. * <strong>The Interpretation:</strong> Rather than ignoring these states, Dirac eventually proposed they represented “holes” in an infinite sea of electrons (the <strong>Dirac Sea</strong>). * <strong>The Positron:</strong> He predicted a particle with the same mass as the electron but an opposite (positive) charge. * <strong>Discovery:</strong> In 1932, <strong>Carl Anderson</strong> experimentally discovered the <strong>positron</strong>, confirming Dirac’s theory and proving the existence of <strong>antimatter</strong>.</p>
</section>
<section id="notation-formalism-the-language-of-quantum-computing" class="level2">
<h2 class="anchored" data-anchor-id="notation-formalism-the-language-of-quantum-computing">4. Notation &amp; Formalism (The Language of Quantum Computing)</h2>
<p>Dirac created the standard “language” used in modern quantum mechanics and quantum computing. * <strong>Bra-Ket Notation:</strong> A shorthand for vectors and inner products in Hilbert space. * <strong>Ket:</strong> <img src="https://latex.codecogs.com/png.latex?%7C%20%5Cpsi%20%5Crangle"> (a state vector). * <strong>Bra:</strong> <img src="https://latex.codecogs.com/png.latex?%5Clangle%20%5Cphi%20%7C"> (the conjugate transpose). * <strong>Bracket:</strong> <img src="https://latex.codecogs.com/png.latex?%5Clangle%20%5Cphi%20%7C%20%5Cpsi%20%5Crangle"> (an inner product/probability amplitude). * <strong>Delta Function:</strong> The <strong>Dirac Delta (<img src="https://latex.codecogs.com/png.latex?%5Cdelta(x)">)</strong>, a “generalized function” used to model point-like densities. * <strong>Poisson Brackets:</strong> He was the first to realize the deep mathematical link between classical Poisson brackets and the quantum commutators <img src="https://latex.codecogs.com/png.latex?%5Bq,%20p%5D%20=%20i%5Chbar">.</p>
</section>
<section id="quantum-electrodynamics-qed" class="level2">
<h2 class="anchored" data-anchor-id="quantum-electrodynamics-qed">5. Quantum Electrodynamics (QED)</h2>
<ul>
<li><strong>Foundations:</strong> Dirac is considered one of the founders of QED, the first theory to successfully quantize the electromagnetic field.</li>
<li><strong>Monopoles:</strong> He theoretically showed that if even a single <strong>magnetic monopole</strong> existed in the universe, it would explain why electric charge is quantized.</li>
</ul>
</section>
<section id="fun-facts-10" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-10">6. Fun Facts</h2>
<ul>
<li><strong>Q: What two theories did the Dirac Equation unify?</strong></li>
<li><strong>A:</strong> Quantum Mechanics and Special Relativity.</li>
<li><strong>Q: What did his equation predict that was later discovered by Carl Anderson?</strong></li>
<li><strong>A:</strong> The Positron (Antimatter).</li>
<li><strong>Q: What is the significance of <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%5Crangle"> in your coding work (Qiskit/PennyLane)?</strong></li>
<li><strong>A:</strong> It is Dirac’s <strong>Ket</strong> notation, representing the quantum state vector.</li>
<li><strong>Q: What was Dirac’s “Mathematical Beauty” principle?</strong></li>
<li><strong>A:</strong> He believed that physical laws should have mathematical beauty and that a beautiful equation was more likely to be “right” than an ugly one that fit data.</li>
</ul>
</section>
</section>
<section id="john-von-neumann-1903-1957" class="level1">
<h1>John von Neumann (1903-1957)</h1>
<section id="biographical-professional-context-5" class="level2">
<h2 class="anchored" data-anchor-id="biographical-professional-context-5">1. Biographical &amp; Professional Context</h2>
<ul>
<li><strong>Origin:</strong> Hungarian-American mathematician, physicist, and computer scientist born in <strong>Budapest</strong>.</li>
<li><strong>Prodigy:</strong> Known for his photographic memory and lightning-fast mental calculations (reportedly divided 8-digit numbers in his head by age six).</li>
<li><strong>The “Martians”:</strong> Part of a group of brilliant Hungarian scientists (along with Szilard and Teller) nicknamed “The Martians” for their seemingly superhuman intelligence.</li>
<li><strong>Career:</strong> A founding member of the <strong>Institute for Advanced Study (IAS)</strong> in Princeton, working alongside Einstein and Gödel.</li>
<li><strong>War Effort:</strong> Played a critical role in the <strong>Manhattan Project</strong>, specifically the design of the explosive lenses needed for the implosion-type atomic bomb.</li>
</ul>
</section>
<section id="foundations-of-quantum-mechanics-1932" class="level2">
<h2 class="anchored" data-anchor-id="foundations-of-quantum-mechanics-1932">2. Foundations of Quantum Mechanics (1932)</h2>
<p>Before von Neumann, quantum mechanics was a collection of brilliant but loosely connected ideas (Schrödinger’s waves vs.&nbsp;Heisenberg’s matrices). * <strong>The Mathematical Synthesis:</strong> In his book <em>Mathematical Foundations of Quantum Mechanics</em>, he proved that Wave Mechanics and Matrix Mechanics were mathematically equivalent. * <strong>Hilbert Space:</strong> He introduced the rigorous framework of <strong>Hilbert Space</strong> (<img src="https://latex.codecogs.com/png.latex?%5Cmathcal%7BH%7D">) as the setting for all quantum states. * <strong>Operators:</strong> Defined physical observables as <strong>Hermitian operators</strong> acting on that space. * <strong>Density Matrix:</strong> Introduced the <strong>Density Matrix</strong> (<img src="https://latex.codecogs.com/png.latex?%5Crho">), which is essential for describing “mixed states” and is a core concept in modern quantum information theory and your work with <strong>PennyLane/Qiskit</strong>.</p>
</section>
<section id="computer-science-the-von-neumann-architecture" class="level2">
<h2 class="anchored" data-anchor-id="computer-science-the-von-neumann-architecture">3. Computer Science &amp; The Von Neumann Architecture</h2>
<p>He is the father of modern computing as we know it today. * <strong>Von Neumann Architecture:</strong> Proposed the design where the <strong>instruction data</strong> and the <strong>program data</strong> are stored in the same memory. * <strong>Components:</strong> Defined the standard structure: 1. A processing unit (ALU and registers). 2. A control unit (instruction register and program counter). 3. Memory. 4. External mass storage. 5. Input/Output mechanisms. * <strong>Stochastic Computing:</strong> Explored how to build reliable computers from unreliable components, a precursor to error-correction theories.</p>
</section>
<section id="game-theory-economics" class="level2">
<h2 class="anchored" data-anchor-id="game-theory-economics">4. Game Theory &amp; Economics</h2>
<ul>
<li><strong>Minimax Theorem (1928):</strong> Proved that in zero-sum games with perfect information, there is always a strategy that minimizes the maximum possible loss for both players.</li>
<li><strong>Theory of Games and Economic Behavior:</strong> Co-authored with Oskar Morgenstern, this founded the entire field of <strong>Game Theory</strong>, revolutionizing economics and social sciences.</li>
</ul>
</section>
<section id="cellular-automata-self-replication" class="level2">
<h2 class="anchored" data-anchor-id="cellular-automata-self-replication">5. Cellular Automata &amp; Self-Replication</h2>
<ul>
<li><strong>Self-Replicating Machines:</strong> He designed a theoretical “Universal Constructor” that could create a copy of itself, proving that machine reproduction was mathematically possible.</li>
<li><strong>Cellular Automata:</strong> Created the first cellular automata models (later popularized by Conway’s “Game of Life”) to study complex systems.</li>
</ul>
</section>
<section id="fun-facts-11" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-11">6. Fun Facts</h2>
<ul>
<li><strong>Q: What was von Neumann’s main contribution to the QM debate?</strong></li>
<li><strong>A:</strong> He provided the rigorous mathematical proof (using Hilbert Space) that unified the different versions of quantum mechanics.</li>
<li><strong>Q: What is the “Von Neumann Bottleneck”?</strong></li>
<li><strong>A:</strong> The limited throughput between the CPU and memory in his standard architecture, which restricts processing speed.</li>
<li><strong>Q: What mathematical object did he introduce to describe mixed quantum states?</strong></li>
<li><strong>A:</strong> The <strong>Density Matrix</strong> (<img src="https://latex.codecogs.com/png.latex?%5Crho">).</li>
<li><strong>Q: What was his role in the Cold War?</strong></li>
<li><strong>A:</strong> He was a key strategist for the U.S. government, applying Game Theory to nuclear deterrence and the “Mutually Assured Destruction” (MAD) doctrine.</li>
</ul>
</section>
</section>
<section id="felix-bloch-1905-1983" class="level1">
<h1>Felix Bloch (1905-1983)</h1>
<section id="biographical-academic-context-1" class="level2">
<h2 class="anchored" data-anchor-id="biographical-academic-context-1">1. Biographical &amp; Academic Context</h2>
<ul>
<li><strong>Origin:</strong> Swiss physicist born in <strong>Zürich</strong>.</li>
<li><strong>Academic Pedigree:</strong> He was the <strong>first graduate student</strong> of Werner Heisenberg at the University of Leipzig.</li>
<li><strong>Global Career:</strong> Fled Nazi Germany in 1933 and became the first professor of theoretical physics at <strong>Stanford University</strong>.</li>
<li><strong>Nobel Prize (1952):</strong> Shared with Edward Purcell for the development of new methods for nuclear magnetic precision measurements (<strong>Nuclear Magnetic Resonance or NMR</strong>).</li>
<li><strong>CERN:</strong> He served as the <strong>first Director-General of CERN</strong> in Geneva (1954–1955).</li>
</ul>
</section>
<section id="solid-state-physics-bloch-waves" class="level2">
<h2 class="anchored" data-anchor-id="solid-state-physics-bloch-waves">2. Solid State Physics: Bloch Waves</h2>
<p>Before Bloch, it was a mystery how electrons could move through a solid metal without being scattered by every single atom. * <strong>Bloch’s Theorem:</strong> He applied quantum mechanics to crystal lattices. He proved that electrons in a periodic potential (like a crystal) move as “waves” modulated by the lattice. * <strong>The Formula (Bloch Function):</strong> <img src="https://latex.codecogs.com/png.latex?%5Cpsi_%7Bn%5Cmathbf%7Bk%7D%7D(%5Cmathbf%7Br%7D)%20=%20e%5E%7Bi%5Cmathbf%7Bk%7D%20%5Ccdot%20%5Cmathbf%7Br%7D%7D%20u_%7Bn%5Cmathbf%7Bk%7D%7D(%5Cmathbf%7Br%7D)"> * <strong>Significance:</strong> This is the basis of the <strong>Energy Band Theory</strong> (conductors, insulators, and semiconductors). Your modern computer and the SENG hardware you study rely entirely on this principle.</p>
</section>
<section id="nuclear-magnetic-resonance-nmr" class="level2">
<h2 class="anchored" data-anchor-id="nuclear-magnetic-resonance-nmr">3. Nuclear Magnetic Resonance (NMR)</h2>
<p>Bloch discovered a way to measure the magnetic moment of atomic nuclei in liquids and solids. * <strong>The Concept:</strong> When placed in a strong magnetic field, nuclei align with the field. By applying a radio-frequency (RF) field, the nuclei “flip” or precess. * <strong>Bloch Equations:</strong> A set of macroscopic equations that describe the nuclear magnetization <img src="https://latex.codecogs.com/png.latex?M"> as a function of time. * <strong>Legacy:</strong> This discovery led directly to the invention of <strong>MRI (Magnetic Resonance Imaging)</strong> in medicine.</p>
</section>
<section id="the-bloch-sphere-quantum-computing-link" class="level2">
<h2 class="anchored" data-anchor-id="the-bloch-sphere-quantum-computing-link">4. The Bloch Sphere (Quantum Computing Link)</h2>
<p>While the “Bloch Sphere” is a geometric representation named in his honor, it is derived from his work on magnetic resonance and the spin of particles. * <strong>Definition:</strong> A geometrical representation of the pure state space of a two-level quantum mechanical system (<strong>a qubit</strong>). * <strong>Coordinates:</strong> Any qubit state <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%5Crangle"> can be represented as a point on the surface of the sphere: <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%5Crangle%20=%20%5Ccos%5Cleft(%5Cfrac%7B%5Ctheta%7D%7B2%7D%5Cright)%7C0%5Crangle%20+%20e%5E%7Bi%5Cphi%7D%5Csin%5Cleft(%5Cfrac%7B%5Ctheta%7D%7B2%7D%5Cright)%7C1%5Crangle"> * <strong>Application:</strong> In <strong>PennyLane</strong> or <strong>Qiskit</strong>, the Bloch Sphere is the standard way to visualize gate rotations (X, Y, Z gates).</p>
</section>
<section id="magnetism-neutrons" class="level2">
<h2 class="anchored" data-anchor-id="magnetism-neutrons">5. Magnetism &amp; Neutrons</h2>
<ul>
<li><strong>Spin Waves:</strong> He developed the theory of “magnons” (spin waves) to explain how magnetization changes with temperature.</li>
<li><strong>Neutron Moment:</strong> He performed the first precise measurement of the magnetic moment of the neutron.</li>
</ul>
</section>
<section id="fun-facts-12" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-12">6. Fun Facts</h2>
<ul>
<li><strong>Q: What is a Bloch Wave?</strong></li>
<li><strong>A:</strong> A quantum mechanical wave function for a particle (usually an electron) moving in a periodic potential/crystal lattice.</li>
<li><strong>Q: What did his Nobel-winning work lead to?</strong></li>
<li><strong>A:</strong> Nuclear Magnetic Resonance (NMR) and MRI technology.</li>
<li><strong>Q: How does his work relate to semiconductors?</strong></li>
<li><strong>A:</strong> His Band Theory explains why some materials conduct electricity and others don’t, based on the behavior of electrons in crystals.</li>
<li><strong>Q: What is the significance of the Bloch Sphere in SENG/Quantum labs?</strong></li>
<li><strong>A:</strong> It is the primary tool for visualizing the state and rotation of a single qubit.</li>
</ul>
</section>
</section>
<section id="claude-shannon-1916-2001" class="level1">
<h1>Claude Shannon (1916-2001)</h1>
<section id="biographical-professional-context-6" class="level2">
<h2 class="anchored" data-anchor-id="biographical-professional-context-6">1. Biographical &amp; Professional Context</h2>
<ul>
<li><strong>Origin:</strong> American mathematician and electrical engineer born in <strong>Michigan</strong>.</li>
<li><strong>Education:</strong> Dual degrees in Mathematics and Electrical Engineering from the University of Michigan; PhD from MIT.</li>
<li><strong>The “Most Important Master’s Thesis”:</strong> At age 21, he wrote <em>A Symbolic Analysis of Relay and Switching Circuits</em>, which changed the world by linking logic to electronics.</li>
<li><strong>Career:</strong> Spent much of his career at <strong>Bell Labs</strong> and <strong>MIT</strong>.</li>
<li><strong>Personality:</strong> Known for his playful genius; he famously invented a flame-throwing trumpet, a motorized pogo stick, and “The Ultimate Machine” (a box that turns itself off).</li>
</ul>
</section>
<section id="digital-circuit-theory-1937" class="level2">
<h2 class="anchored" data-anchor-id="digital-circuit-theory-1937">2. Digital Circuit Theory (1937)</h2>
<p>Before Shannon, circuit design was an ad-hoc art. He proved that it was a science based on <strong>Boolean Algebra</strong>. * <strong>The Discovery:</strong> He showed that the “on/off” states of electrical switches (relays) could represent the “True/False” values of Boolean logic. * <strong>Significance:</strong> This is the foundation of all modern digital computers. Every <strong>SENG</strong> course you take on architecture or logic gates traces back to this specific realization.</p>
</section>
<section id="information-theory-1948" class="level2">
<h2 class="anchored" data-anchor-id="information-theory-1948">3. Information Theory (1948)</h2>
<p>Shannon founded the entire field of Information Theory with his landmark paper, <em>A Mathematical Theory of Communication</em>. * <strong>The Bit:</strong> He popularized the term “bit” (binary digit) as the fundamental unit of information. * <strong>Source Coding Theorem:</strong> Proved that there is a statistical limit to how much a message can be compressed without losing information (the origin of ZIP files and JPEG compression). * <strong>Noisy-Channel Coding Theorem:</strong> Proved that data can be transmitted with zero errors over a “noisy” channel, provided the transmission rate is below the <strong>Shannon Capacity</strong> (<img src="https://latex.codecogs.com/png.latex?C">).</p>
</section>
<section id="entropy-in-information" class="level2">
<h2 class="anchored" data-anchor-id="entropy-in-information">4. Entropy in Information</h2>
<p>Shannon borrowed the concept of entropy from thermodynamics (specifically from <strong>Boltzmann</strong>) to measure the “uncertainty” or “information content” of a message. * <strong>The Formula (Shannon Entropy):</strong> <img src="https://latex.codecogs.com/png.latex?H(X)%20=%20-%5Csum_%7Bi=1%7D%5E%7Bn%7D%20P(x_i)%20%5Clog_2%20P(x_i)"> * <strong>Interpretation:</strong> * If a result is certain (<img src="https://latex.codecogs.com/png.latex?P=1">), entropy is <strong>0</strong>. * If a result is a coin flip (<img src="https://latex.codecogs.com/png.latex?P=0.5">), entropy is maximized (1 bit of information).</p>
</section>
<section id="cryptography-ai" class="level2">
<h2 class="anchored" data-anchor-id="cryptography-ai">5. Cryptography &amp; AI</h2>
<ul>
<li><strong>Communication Theory of Secrecy Systems:</strong> Shannon proved that the <strong>One-Time Pad</strong> is the only unbreakable cipher (provided the key is random and never reused).</li>
<li><strong>Artificial Intelligence:</strong> He created <strong>Theseus</strong>, a mechanical mouse that could learn to navigate a maze using a memory of relay switches—one of the earliest examples of machine learning and AI.</li>
<li><strong>Computer Chess:</strong> Wrote the first significant paper on how a computer could be programmed to play chess (<em>Programming a Computer for Playing Chess</em>).</li>
</ul>
</section>
<section id="fun-facts-13" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-13">6. Fun Facts</h2>
<ul>
<li><strong>Q: What did Shannon bridge in his Master’s thesis?</strong></li>
<li><strong>A:</strong> Electrical engineering (switching circuits) and Philosophy/Logic (Boolean Algebra).</li>
<li><strong>Q: What is the “Shannon Limit”?</strong></li>
<li><strong>A:</strong> The maximum rate at which information can be transmitted over a communication channel with a specific noise level.</li>
<li><strong>Q: How does Shannon Entropy relate to Data Mining (SENG 474)?</strong></li>
<li><strong>A:</strong> Entropy is used in <strong>Decision Trees</strong> (like ID3 or C4.5) to calculate <strong>Information Gain</strong> when splitting data.</li>
<li><strong>Q: What was “Theseus”?</strong></li>
<li><strong>A:</strong> A mechanical mouse that demonstrated the first practical application of “electronic” learning/memory.</li>
</ul>
</section>
</section>
<section id="richard-feynman-1918-1988" class="level1">
<h1>Richard Feynman (1918-1988)</h1>
<section id="biographical-professional-context-7" class="level2">
<h2 class="anchored" data-anchor-id="biographical-professional-context-7">1. Biographical &amp; Professional Context</h2>
<ul>
<li><strong>Origin:</strong> American theoretical physicist born in <strong>Queens, New York</strong>.</li>
<li><strong>Manhattan Project:</strong> Recruited as a young prodigy to work at Los Alamos, where he oversaw the human “computer” groups calculating implosion rates.</li>
<li><strong>The “Great Explainer”:</strong> Known for his ability to explain complex concepts in simple terms (The Feynman Lectures on Physics).</li>
<li><strong>Nobel Prize (1965):</strong> Shared with Tomonaga and Schwinger for fundamental work in <strong>Quantum Electrodynamics (QED)</strong>.</li>
<li><strong>Challenger Disaster:</strong> In 1986, he served on the Rogers Commission and famously demonstrated the failure of O-rings using a glass of ice water.</li>
</ul>
</section>
<section id="quantum-electrodynamics-qed-feynman-diagrams" class="level2">
<h2 class="anchored" data-anchor-id="quantum-electrodynamics-qed-feynman-diagrams">2. Quantum Electrodynamics (QED) &amp; Feynman Diagrams</h2>
<p>Feynman revolutionized how physicists calculate particle interactions. * <strong>Feynman Diagrams:</strong> Instead of massive, complex equations, he introduced a visual bookkeeping system for the interactions of subatomic particles. * <strong>Components:</strong> * Straight lines represent fermions (like electrons). * Wavy/wiggly lines represent bosons (like photons). * Vertices represent interactions. * <strong>Significance:</strong> These diagrams are actually shorthand for complex mathematical integrals used to calculate “scattering amplitudes.”</p>
<p>[Image of a Feynman diagram showing electron-positron annihilation]</p>
</section>
<section id="the-path-integral-formulation" class="level2">
<h2 class="anchored" data-anchor-id="the-path-integral-formulation">3. The Path Integral Formulation</h2>
<p>Feynman provided a third way to look at quantum mechanics (distinct from Schrödinger’s waves and Heisenberg’s matrices). * <strong>The Concept:</strong> A particle doesn’t just take one path from point A to point B; it takes <strong>every possible path</strong> simultaneously. * <strong>The Math:</strong> The probability amplitude is found by summing the phases of all possible paths: <img src="https://latex.codecogs.com/png.latex?%5Cpsi(x,%20t)%20=%20%5Cint%20%5Cmathcal%7BD%7D%5Bx(t)%5D%20e%5E%7Bi%20S%5Bx(t)%5D%20/%20%5Chbar%7D"> * <strong>S:</strong> The <strong>Action</strong> of the path. * <strong>Significance:</strong> This formulation is the backbone of modern Quantum Field Theory (QFT).</p>
</section>
<section id="the-father-of-quantum-computing-1981" class="level2">
<h2 class="anchored" data-anchor-id="the-father-of-quantum-computing-1981">4. The Father of Quantum Computing (1981)</h2>
<p>In a famous keynote titled <em>“Simulating Physics with Computers”</em>, Feynman noted that classical computers could not efficiently simulate quantum systems because of the exponential complexity. * <strong>The Proposal:</strong> “Nature isn’t classical, dammit, and if you want to make a simulation of nature, you’d better make it quantum mechanical.” * <strong>The Goal:</strong> He proposed using a computer governed by quantum laws to simulate quantum physics—the birth of the field you are studying in <strong>PennyLane</strong> and <strong>Qiskit</strong>.</p>
</section>
<section id="nanotechnology-theres-plenty-of-room-at-the-bottom" class="level2">
<h2 class="anchored" data-anchor-id="nanotechnology-theres-plenty-of-room-at-the-bottom">5. Nanotechnology: “There’s Plenty of Room at the Bottom”</h2>
<p>In a 1959 talk, Feynman predicted the field of nanotechnology. * <strong>The Vision:</strong> He suggested that individual atoms could be manipulated and that entire encyclopedias could be written on the head of a pin. * <strong>Impact:</strong> This inspired the development of scanning tunneling microscopes and the modern field of molecular engineering.</p>
</section>
<section id="fun-facts-14" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-14">6. Fun Facts</h2>
<ul>
<li><strong>Q: What is the “Feynman Technique” for learning?</strong></li>
<li><strong>A:</strong> Explain a concept to a child (or someone with no background); identify your gaps in understanding; go back to the source material; simplify and create an analogy.</li>
<li><strong>Q: What problem did Feynman Diagrams solve?</strong></li>
<li><strong>A:</strong> They made the incredibly difficult calculations of Quantum Electrodynamics (QED) manageable and intuitive.</li>
<li><strong>Q: How did Feynman contribute to the Challenger investigation?</strong></li>
<li><strong>A:</strong> He proved that the O-ring seals lost elasticity at freezing temperatures, leading to the shuttle’s explosion.</li>
<li><strong>Q: What was his stance on the simulation of physics?</strong></li>
<li><strong>A:</strong> He argued that only a quantum computer could accurately and efficiently simulate the quantum world.</li>
</ul>
</section>
</section>
<section id="john-stewart-bell-1928-1990" class="level1">
<h1>John Stewart Bell (1928-1990)</h1>
<section id="biographical-professional-context-8" class="level2">
<h2 class="anchored" data-anchor-id="biographical-professional-context-8">1. Biographical &amp; Professional Context</h2>
<ul>
<li><strong>Origin:</strong> Northern Irish physicist born in <strong>Belfast</strong>.</li>
<li><strong>Career:</strong> Spent most of his career at <strong>CERN</strong> in Geneva as a theoretical particle physicist, though his most famous work was done as a “hobby” in foundations of quantum mechanics.</li>
<li><strong>Legacy:</strong> Often described as the man who proved “Einstein was wrong” about local realism, though he deeply respected Einstein’s desire for clarity.</li>
<li><strong>The “Bell’s Theorem” Paper (1964):</strong> Titled <em>On the Einstein-Podolsky-Rosen Paradox</em>, it is one of the most cited and profound papers in the history of science.</li>
</ul>
</section>
<section id="the-epr-paradox-local-realism" class="level2">
<h2 class="anchored" data-anchor-id="the-epr-paradox-local-realism">2. The EPR Paradox &amp; Local Realism</h2>
<p>Before Bell, the physics community mostly ignored the <strong>EPR (Einstein-Podolsky-Rosen) Paradox</strong>. * <strong>Einstein’s View:</strong> Quantum mechanics must be “incomplete.” There must be <strong>Hidden Variables</strong> that determine a particle’s state before we measure it. * <strong>Local Realism:</strong> The belief that: 1. <strong>Realism:</strong> Objects have definite properties even when not observed. 2. <strong>Locality:</strong> No influence can travel faster than the speed of light.</p>
</section>
<section id="bells-theorem-bells-inequality" class="level2">
<h2 class="anchored" data-anchor-id="bells-theorem-bells-inequality">3. Bell’s Theorem (Bell’s Inequality)</h2>
<p>Bell proved that no theory based on <strong>Local Hidden Variables</strong> could ever reproduce all the predictions of quantum mechanics. * <strong>The Concept:</strong> He created a mathematical “limit” (an inequality) for the correlation between measurements of two entangled particles. * <strong>The Result:</strong> If quantum mechanics is correct, the correlation between particles will <strong>violate</strong> this inequality. * <strong>The Inequality (CHSH version):</strong> <img src="https://latex.codecogs.com/png.latex?%7CS%7C%20=%20%7CE(a,%20b)%20-%20E(a,%20b')%20+%20E(a',%20b)%20+%20E(a',%20b')%7C%20%5Cle%202"> * <strong>Significance:</strong> Quantum mechanics predicts a value of <img src="https://latex.codecogs.com/png.latex?2%5Csqrt%7B2%7D%20%5Capprox%202.82">, which is greater than 2. This means nature is <strong>non-local</strong>.</p>
</section>
<section id="experimental-confirmation-1" class="level2">
<h2 class="anchored" data-anchor-id="experimental-confirmation-1">4. Experimental Confirmation</h2>
<p>Bell’s work was purely theoretical until others built experiments to test it. * <strong>Alain Aspect (1982):</strong> Conducted the first definitive experiment using entangled photons, proving that Bell’s Inequality was violated. * <strong>2022 Nobel Prize:</strong> Awarded to Aspect, Clauser, and Zeilinger for these experiments, directly validating Bell’s 1964 theorem. * <strong>Impact:</strong> This confirmed that <strong>Entanglement</strong> is a “spooky” but real connection that defies classical local logic.</p>
</section>
<section id="speakable-and-unspeakable-in-quantum-mechanics" class="level2">
<h2 class="anchored" data-anchor-id="speakable-and-unspeakable-in-quantum-mechanics">5. “Speakable and Unspeakable in Quantum Mechanics”</h2>
<ul>
<li><strong>The Book:</strong> A collection of Bell’s essays where he argues for precision in language (the “Speakable”).</li>
<li><strong>Criticism of “Measurement”:</strong> He disliked the word “measurement” because it implies a human observer is necessary; he preferred the term <strong>“beables”</strong> for things that actually exist in the physical world.</li>
<li><strong>The “Bertlmann’s Socks” Analogy:</strong> A famous analogy he used to explain the difference between classical correlation (wearing matching socks) and quantum entanglement.</li>
</ul>
</section>
<section id="fun-facts-15" class="level2">
<h2 class="anchored" data-anchor-id="fun-facts-15">6. Fun Facts</h2>
<ul>
<li><strong>Q: What did Bell’s Theorem prove?</strong></li>
<li><strong>A:</strong> That no local hidden variable theory can replicate the predictions of quantum mechanics (i.e., the universe is non-local).</li>
<li><strong>Q: What is a “Bell State” in Quantum Computing?</strong></li>
<li><strong>A:</strong> One of the four specific maximally entangled states of two qubits (e.g., <img src="https://latex.codecogs.com/png.latex?%7C%5CPhi%5E+%5Crangle%20=%20%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D(%7C00%5Crangle%20+%20%7C11%5Crangle)">).</li>
<li><strong>Q: How does this relate to SENG/Quantum labs (Qiskit/PennyLane)?</strong></li>
<li><strong>A:</strong> When you use a <strong>CNOT gate</strong> and a <strong>Hadamard gate</strong> to entangle two qubits, you are creating a system that violates Bell’s Inequality.</li>
<li><strong>Q: What is the “Superdeterminism” loophole?</strong></li>
<li><strong>A:</strong> A theoretical way to save locality by suggesting that the universe is completely predetermined, including the choices of the experimenters.</li>
</ul>


</section>
</section>

 ]]></description>
  <category>quantum</category>
  <category>history</category>
  <guid>https://notes.zakacat.ca/notebooks/history-of-quantum-physicists.html</guid>
  <pubDate>Sun, 08 Mar 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Quantum Algorithms and Software Engineering</title>
  <dc:creator>Zak Toews</dc:creator>
  <link>https://notes.zakacat.ca/notebooks/TPP-P2-Zak-Toews.html</link>
  <description><![CDATA[ 




<center>
<section id="quantum-algorithms-and-software-engineering-term-portfolio-project" class="level1">
<h1><strong>Quantum Algorithms and Software Engineering: Term Portfolio Project</strong></h1>
<section id="by-zak-toews" class="level3">
<h3 class="anchored" data-anchor-id="by-zak-toews">By Zak Toews</h3>
</section>
<section id="th-year-software-engineering-student" class="level3">
<h3 class="anchored" data-anchor-id="th-year-software-engineering-student">4th Year Software Engineering Student</h3>
</section></section></center>


<section id="table-of-contents" class="level1">
<h1>Table of Contents</h1>
<ol type="1">
<li>Part 1: Documenting my Quantum Journey
<ol type="1">
<li>Linear algebra fundamentals</li>
<li>LaTeX/Dirac notation cheat sheet</li>
<li>First circuits in Qiskit &amp; PennyLane</li>
<li>Motivating other students</li>
<li>Favourite algorithm so far</li>
<li>Grover’s algorithm challenges</li>
<li>Insights &amp; epiphanies, Part 1</li>
<li>Generative AI as a learning tool</li>
<li>GenAI prompt log</li>
<li>Part 1 Bibliography</li>
</ol></li>
<li>Part 2: Documenting my Quantum Journey
<ol type="1">
<li>Quantum Fourier Transform (QFT)</li>
<li>Quantum Phase Estimation (QPE)</li>
<li>Grover’s algorithm, revisited</li>
<li>Favourite algorithm &amp; why</li>
<li>Eigenvalues &amp; eigenstates</li>
<li>Hybrid decomposition strategies</li>
<li>Favourite decomposition strategy</li>
<li>Grad student application summaries</li>
<li>Most inspiring application</li>
<li>Generative AI, revisited</li>
<li>Résumé takeaways</li>
<li>Insights &amp; epiphanies, Part 2</li>
<li>Part 2 Bibliography</li>
</ol></li>
</ol>
<section id="part-1" class="level2">
<h2 class="anchored" data-anchor-id="part-1"><strong>Part 1: Documenting my Quantum Journey</strong></h2>
<section id="p1-q1" class="level3">
<h3 class="anchored" data-anchor-id="p1-q1">1. <em>How did you get up to speed in basic linear algebra (e.g., Euler formula, complex plane, linear transformations or operators, eigenvectors and eigenvalues), including which resources you consulted in this process?</em></h3>
<p>In this course, it was brought to our attention that the foundations of Quantum Computing relies on a understanding of linear algerbra, trigonometry, complex numbers, and matrix operations. We have yet to work with eigenvalues and eigenvectors.</p>
<p>For the matrix algebra, I had recalled <em>some</em> of my knowledge from my first year course which is almost 5 years ago now. But, I was not too concerned as if I had learned it fine the first time, I could learn it again without much of a hitch. I looked up the basic Matrix Operations 1, practice was real time during Quizzes and Assignments, and I would verify my answers with some tools [2][3]. Although, I am still pretty weary about trusting the math that AI pumps out, but Gemini is pretty good at it now.</p>
<p>For trigonometry and Euler’s formula, I understand the basics, but I have been consistently going back to the slides that contain Euler’s identity then trying to imagine what how the phase change affects the qubit on the Bloch sphere. The complex plane as it is has been drilled home for me from classes such as ECE 360 Control Systems (T_T).</p>
<p>I included some code to show the different basis states below.</p>
<div id="939a7f3f-3a74-4107-b87f-32e7537d20aa" class="cell" data-execution_count="1">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> qiskit.visualization <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> plot_bloch_vector</span>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Coordinates for the 6 basis states [x, y, z]</span></span>
<span id="cb1-5">states <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb1-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"|0&gt;"</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>],</span>
<span id="cb1-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"|1&gt;"</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>],</span>
<span id="cb1-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"|+&gt;"</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],</span>
<span id="cb1-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"|-&gt;"</span>: [<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],</span>
<span id="cb1-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"|i&gt;"</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],</span>
<span id="cb1-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"|-i&gt;"</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb1-12">}</span>
<span id="cb1-13"></span>
<span id="cb1-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Create subplots with 3D projection</span></span>
<span id="cb1-15">fig <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.figure(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span>
<span id="cb1-16"></span>
<span id="cb1-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> i, (label, coord) <span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(states.items()):</span>
<span id="cb1-18">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add a 3D subplot for each basis vector</span></span>
<span id="cb1-19">    ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fig.add_subplot(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, projection<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'3d'</span>)</span>
<span id="cb1-20">    plot_bloch_vector(coord, title<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>label, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax)</span>
<span id="cb1-21"></span>
<span id="cb1-22">plt.show()</span></code></pre></div>
</details>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://notes.zakacat.ca/notebooks/TPP-P2-Zak-Toews_files/figure-html/cell-2-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="p1-q2" class="level3">
<h3 class="anchored" data-anchor-id="p1-q2">2. <em>How did you get started in documenting linear algebra formulas (e.g., Euler formula or matrices) using LaTeX Markdown in Jupyter Notebooks? Develop your own cheat sheet of the quantum computing formulas and Dirac notation to ease assignment typesetting.</em></h3>
<p>To get started with the formulas and matrices that I would need, I would pull the relevant information from the slides. I had actually done my assignment by hand to avoid the typesetting, but for the next assignment I will be able to copy and paste from the following cheat sheet:</p>
</section>
<section id="matrix-symbols-and-multiplication-properties" class="level3">
<h3 class="anchored" data-anchor-id="matrix-symbols-and-multiplication-properties">Matrix Symbols and Multiplication Properties</h3>
<p><strong>1. Definitions</strong> * <strong>Complex Conjugate:</strong> <img src="https://latex.codecogs.com/png.latex?A%5E*"> or <img src="https://latex.codecogs.com/png.latex?%5Cbar%7BA%7D"> * <strong>Transpose:</strong> <img src="https://latex.codecogs.com/png.latex?A%5ET"> * <strong>Inverse:</strong> <img src="https://latex.codecogs.com/png.latex?A%5E%7B-1%7D"> * <strong>Conjugate Transpose (Adjoint):</strong> <img src="https://latex.codecogs.com/png.latex?A%5E%5Cdagger"></p>
<p><strong>2. Multiplication Properties</strong> <img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A&amp;%5Ctext%7BDistributive:%7D%20&amp;%20A(B%20+%20C)%20&amp;=%20AB%20+%20AC%20%5C%5C%0A&amp;%5Ctext%7BAssociative:%7D%20&amp;%20(AB)C%20&amp;=%20A(BC)%20%5C%5C%0A&amp;%5Ctext%7BNon-Commutative:%7D%20&amp;%20AB%20&amp;%5Cneq%20BA%20%5Cquad%20%5Ctext%7B(Generally)%7D%20%5C%5C%0A%5C%5C%0A&amp;%5Ctext%7BTranspose%20of%20Product:%7D%20&amp;%20(AB)%5ET%20&amp;=%20B%5ET%20A%5ET%20%5C%5C%0A&amp;%5Ctext%7BInverse%20of%20Product:%7D%20&amp;%20(AB)%5E%7B-1%7D%20&amp;=%20B%5E%7B-1%7D%20A%5E%7B-1%7D%20%5C%5C%0A&amp;%5Ctext%7BAdjoint%20of%20Product:%7D%20&amp;%20(AB)%5E%5Cdagger%20&amp;=%20B%5E%5Cdagger%20A%5E%5Cdagger%0A%5Cend%7Baligned%7D%0A"></p>
<p><strong>3. Properties of Unitary Matrices (<img src="https://latex.codecogs.com/png.latex?U">)</strong> A matrix <img src="https://latex.codecogs.com/png.latex?U"> is unitary if its conjugate transpose is also its inverse. <img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A&amp;%5Ctext%7BDefining%20Condition:%7D%20&amp;%20U%5E%5Cdagger%20U%20&amp;=%20UU%5E%5Cdagger%20=%20I%20%5C%5C%0A&amp;%5Ctext%7BInverse%20Relationship:%7D%20&amp;%20U%5E%7B-1%7D%20&amp;=%20U%5E%5Cdagger%20%5C%5C%0A&amp;%5Ctext%7BProduct%20of%20Unitaries:%7D%20&amp;%20(UV)%5E%5Cdagger%20&amp;=%20V%5E%5Cdagger%20U%5E%5Cdagger%20%5Cquad%20%5Ctext%7B(The%20product%20%7D%20UV%20%5Ctext%7B%20is%20also%20unitary)%7D%20%5C%5C%0A&amp;%5Ctext%7BNorm%20Preservation:%7D%20&amp;%20%5Clangle%20U%5Cpsi%20%7C%20U%5Cpsi%20%5Crangle%20&amp;=%20%5Clangle%20%5Cpsi%20%7C%20%5Cpsi%20%5Crangle%20%5C%5C%0A&amp;%5Ctext%7BDeterminant:%7D%20&amp;%20%7C%5Cdet(U)%7C%20&amp;=%201%0A%5Cend%7Baligned%7D%0A"></p>
<p><strong>4. Properties of Tensor Products (<img src="https://latex.codecogs.com/png.latex?%5Cotimes">)</strong> <img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A&amp;%5Ctext%7BDistributive:%7D%20&amp;%20A%20%5Cotimes%20(B%20+%20C)%20&amp;=%20(A%20%5Cotimes%20B)%20+%20(A%20%5Cotimes%20C)%20%5C%5C%0A&amp;%5Ctext%7BScalar%20Multiplication:%7D%20&amp;%20c(A%20%5Cotimes%20B)%20&amp;=%20(cA)%20%5Cotimes%20B%20=%20A%20%5Cotimes%20(cB)%20%5C%5C%0A&amp;%5Ctext%7BMixed-Product%20Property:%7D%20&amp;%20(A%20%5Cotimes%20B)(C%20%5Cotimes%20D)%20&amp;=%20(AC)%20%5Cotimes%20(BD)%20%5C%5C%0A%5C%5C%0A&amp;%5Ctext%7BTranspose:%7D%20&amp;%20(A%20%5Cotimes%20B)%5ET%20&amp;=%20A%5ET%20%5Cotimes%20B%5ET%20%5C%5C%0A&amp;%5Ctext%7BConjugate:%7D%20&amp;%20(A%20%5Cotimes%20B)%5E*%20&amp;=%20A%5E*%20%5Cotimes%20B%5E*%20%5C%5C%0A&amp;%5Ctext%7BAdjoint%20(Dagger):%7D%20&amp;%20(A%20%5Cotimes%20B)%5E%5Cdagger%20&amp;=%20A%5E%5Cdagger%20%5Cotimes%20B%5E%5Cdagger%20%5C%5C%0A&amp;%5Ctext%7BInverse:%7D%20&amp;%20(A%20%5Cotimes%20B)%5E%7B-1%7D%20&amp;=%20A%5E%7B-1%7D%20%5Cotimes%20B%5E%7B-1%7D%0A%5Cend%7Baligned%7D%0A"></p>
<p><strong>5. Dirac Notation &amp; Computational Basis</strong> The computational basis for a single qubit consists of the states <img src="https://latex.codecogs.com/png.latex?%7C0%5Crangle"> and <img src="https://latex.codecogs.com/png.latex?%7C1%5Crangle">.</p>
<ul>
<li><p><strong>Column Vectors (Kets):</strong> <img src="https://latex.codecogs.com/png.latex?%7C0%5Crangle%20=%20%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%200%20%5Cend%7Bpmatrix%7D,%20%5Cquad%20%7C1%5Crangle%20=%20%5Cbegin%7Bpmatrix%7D%200%20%5C%5C%201%20%5Cend%7Bpmatrix%7D"></p></li>
<li><p><strong>Row Vectors (Bras):</strong> <img src="https://latex.codecogs.com/png.latex?%5Clangle%200%7C%20=%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%200%20%5Cend%7Bpmatrix%7D,%20%5Cquad%20%5Clangle%201%7C%20=%20%5Cbegin%7Bpmatrix%7D%200%20&amp;%201%20%5Cend%7Bpmatrix%7D"></p></li>
<li><p><strong>Linear Combination of Unit Kets:</strong> A general quantum state <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%5Crangle"> is a superposition: <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%5Crangle%20=%20%5Calpha%7C0%5Crangle%20+%20%5Cbeta%7C1%5Crangle%20=%20%5Cbegin%7Bpmatrix%7D%20%5Calpha%20%5C%5C%20%5Cbeta%20%5Cend%7Bpmatrix%7D"> where <img src="https://latex.codecogs.com/png.latex?%5Calpha,%20%5Cbeta%20%5Cin%20%5Cmathbb%7BC%7D"> and <img src="https://latex.codecogs.com/png.latex?%7C%5Calpha%7C%5E2%20+%20%7C%5Cbeta%7C%5E2%20=%201">.</p></li>
</ul>
<p><strong>Inner Product and Orthnormality</strong> The inner product of two vectors <img src="https://latex.codecogs.com/png.latex?%7C%5Cphi%5Crangle"> and <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%5Crangle"> is written as <img src="https://latex.codecogs.com/png.latex?%5Clangle%20%5Cphi%20%7C%20%5Cpsi%20%5Crangle">. For the computational basis: <img src="https://latex.codecogs.com/png.latex?%5Clangle%20i%20%7C%20j%20%5Crangle%20=%20%5Cdelta_%7Bij%7D%20%5Cimplies%20%5Clangle%200%7C0%5Crangle%20=%201,%20%5Cquad%20%5Clangle%200%7C1%5Crangle%20=%200"></p>
<p><strong>Measurement and the Born Rule</strong> When measuring a state <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%5Crangle%20=%20%5Calpha%7C0%5Crangle%20+%20%5Cbeta%7C1%5Crangle"> in the computational basis:</p>
<ul>
<li><p><strong>Probability of outcome <img src="https://latex.codecogs.com/png.latex?%7C0%5Crangle">:</strong> <img src="https://latex.codecogs.com/png.latex?P(0)%20=%20%7C%5Clangle%200%7C%5Cpsi%5Crangle%7C%5E2%20=%20%7C%5Calpha%7C%5E2"></p></li>
<li><p><strong>Probability of outcome <img src="https://latex.codecogs.com/png.latex?%7C1%5Crangle">:</strong> <img src="https://latex.codecogs.com/png.latex?P(1)%20=%20%7C%5Clangle%201%7C%5Cpsi%5Crangle%7C%5E2%20=%20%7C%5Cbeta%7C%5E2"></p></li>
<li><p><strong>General Born Rule:</strong> For a state <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%5Crangle">, the probability of measuring an eigenvalue associated with eigenvector <img src="https://latex.codecogs.com/png.latex?%7Cx%5Crangle"> is: <img src="https://latex.codecogs.com/png.latex?P(x)%20=%20%7C%5Clangle%20x%7C%5Cpsi%5Crangle%7C%5E2"></p></li>
</ul>
<p><strong>6. Quantum Logic Gates (Single-Qubit)</strong></p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A&amp;%5Cmathbf%7BX%20%5Ctext%7B%20(NOT):%7D%7D%20&amp;%20X%20&amp;=%20%5Cbegin%7Bpmatrix%7D%200%20&amp;%201%20%5C%5C%201%20&amp;%200%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A&amp;%5Cmathbf%7BZ%20%5Ctext%7B%20(Phase%20Flip):%7D%7D%20&amp;%20Z%20&amp;=%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%200%20%5C%5C%200%20&amp;%20-1%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A&amp;%5Cmathbf%7BY%20%5Ctext%7B%20(Bit%20%5C&amp;%20Phase%20Flip):%7D%7D%20&amp;%20Y%20&amp;=%20%5Cbegin%7Bpmatrix%7D%200%20&amp;%20-i%20%5C%5C%20i%20&amp;%200%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A&amp;%5Cmathbf%7BH%20%5Ctext%7B%20(Hadamard):%7D%7D%20&amp;%20H%20&amp;=%20%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D%5Cbegin%7Bpmatrix%7D%201%20&amp;%201%20%5C%5C%201%20&amp;%20-1%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A&amp;%5Cmathbf%7BS%20%5Ctext%7B%20(Phase):%7D%7D%20&amp;%20S%20&amp;=%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%200%20%5C%5C%200%20&amp;%20i%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A&amp;%5Cmathbf%7BT%20%5Ctext%7B%20(%7D%5Cpi/8%5Ctext%7B%20Gate):%7D%7D%20&amp;%20T%20&amp;=%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%200%20%5C%5C%200%20&amp;%20e%5E%7Bi%5Cpi/4%7D%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A&amp;%5Cmathbf%7BP(%5Cphi)%20%5Ctext%7B%20(Phase%20Shift):%7D%7D%20&amp;%20P(%5Cphi)%20&amp;=%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%200%20%5C%5C%200%20&amp;%20e%5E%7Bi%5Cphi%7D%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A&amp;%5Cmathbf%7BR_z(%5Ctheta)%20%5Ctext%7B%20(Rotation):%7D%7D%20&amp;%20R_z(%5Ctheta)%20&amp;=%20%5Cbegin%7Bpmatrix%7D%20e%5E%7B-i%5Ctheta/2%7D%20&amp;%200%20%5C%5C%200%20&amp;%20e%5E%7Bi%5Ctheta/2%7D%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A&amp;%5Cmathbf%7B%5Csqrt%7BX%7D%20%5Ctext%7B%20(SX%20Gate):%7D%7D%20&amp;%20%5Csqrt%7BX%7D%20&amp;=%20%5Cfrac%7B1%7D%7B2%7D%5Cbegin%7Bpmatrix%7D%201+i%20&amp;%201-i%20%5C%5C%201-i%20&amp;%201+i%20%5Cend%7Bpmatrix%7D%0A%5Cend%7Baligned%7D%0A"></p>
<p><strong>7. Common Gate Identities</strong> Note: Identities are often given “up to a global phase” (<img src="https://latex.codecogs.com/png.latex?e%5E%7Bi%5Ctheta%7D">). <img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A&amp;%5Ctext%7BPhase/Rotation%20Relations:%7D%20&amp;%20S%20&amp;=%20P(%5Cpi/2)%20%5Cequiv%20R_z(%5Cpi/2)%20%5C%5C%0A&amp;%20&amp;%20T%20&amp;=%20P(%5Cpi/4)%20%5Cequiv%20R_z(%5Cpi/4)%20%5C%5C%0A&amp;%5Ctext%7BHadamard%20Basis%20Change:%7D%20&amp;%20H%20X%20H%20&amp;=%20Z%20%5C%5C%0A&amp;%20&amp;%20H%20Z%20H%20&amp;=%20X%20%5C%5C%0A&amp;%5Ctext%7BSquare%20Root%20Relations:%7D%20&amp;%20(%5Csqrt%7BX%7D)%5E2%20&amp;=%20X%20%5C%5C%0A&amp;%20&amp;%20S%5E2%20&amp;=%20Z%20%5C%5C%0A&amp;%5Ctext%7BSelf-Inverse%20Gates%20(Hermitian):%7D%20&amp;%20H%5E2%20=%20X%5E2%20&amp;=%20Y%5E2%20=%20Z%5E2%20=%20I%20%5C%5C%0A&amp;%5Ctext%7BPauli%20Multiplication:%7D%20&amp;%20XY%20&amp;=%20iZ,%20%5Cquad%20YZ%20=%20iX,%20%5Cquad%20ZX%20=%20iY%0A%5Cend%7Baligned%7D%0A"></p>
<p><strong>8. Tensor Product of Vectors (<img src="https://latex.codecogs.com/png.latex?n">-qubits)</strong> If we have <img src="https://latex.codecogs.com/png.latex?n"> individual qubits in states <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi_1%5Crangle,%20%7C%5Cpsi_2%5Crangle,%20%5Cdots,%20%7C%5Cpsi_n%5Crangle">, the combined state <img src="https://latex.codecogs.com/png.latex?%7C%5CPsi%5Crangle"> is the tensor product: <img src="https://latex.codecogs.com/png.latex?%7C%5CPsi%5Crangle%20=%20%7C%5Cpsi_1%5Crangle%20%5Cotimes%20%7C%5Cpsi_2%5Crangle%20%5Cotimes%20%5Cdots%20%5Cotimes%20%7C%5Cpsi_n%5Crangle"></p>
<p>For the computational basis, the state <img src="https://latex.codecogs.com/png.latex?%7Cx%5Crangle"> where <img src="https://latex.codecogs.com/png.latex?x"> is a binary string <img src="https://latex.codecogs.com/png.latex?x_1x_2%5Cdots%20x_n">: <img src="https://latex.codecogs.com/png.latex?%7Cx_1%20x_2%20%5Cdots%20x_n%5Crangle%20=%20%7Cx_1%5Crangle%20%5Cotimes%20%7Cx_2%5Crangle%20%5Cotimes%20%5Cdots%20%5Cotimes%20%7Cx_n%5Crangle"> This results in a column vector of size <img src="https://latex.codecogs.com/png.latex?2%5En">.</p>
<p><strong>9. Tensor Product of Matrices (Kronecker Product)</strong> For two matrices <img src="https://latex.codecogs.com/png.latex?A"> (size <img src="https://latex.codecogs.com/png.latex?m%20%5Ctimes%20n">) and <img src="https://latex.codecogs.com/png.latex?B"> (size <img src="https://latex.codecogs.com/png.latex?p%20%5Ctimes%20q">), the tensor product <img src="https://latex.codecogs.com/png.latex?A%20%5Cotimes%20B"> is a matrix of size <img src="https://latex.codecogs.com/png.latex?mp%20%5Ctimes%20nq">: <img src="https://latex.codecogs.com/png.latex?%0AA%20%5Cotimes%20B%20=%20%5Cbegin%7Bpmatrix%7D%0Aa_%7B11%7DB%20&amp;%20a_%7B12%7DB%20&amp;%20%5Cdots%20%5C%5C%0Aa_%7B21%7DB%20&amp;%20a_%7B22%7DB%20&amp;%20%5Cdots%20%5C%5C%0A%5Cvdots%20&amp;%20%5Cvdots%20&amp;%20%5Cddots%0A%5Cend%7Bpmatrix%7D%0A"></p>
<p><strong>10. 2-Qubit Computational Basis</strong> The basis for a 2-qubit system is formed by the tensor product of two 1-qubit basis vectors. There are <img src="https://latex.codecogs.com/png.latex?2%5E2%20=%204"> possible states:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A%7C00%5Crangle%20&amp;=%20%7C0%5Crangle%20%5Cotimes%20%7C0%5Crangle%20=%20%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%200%20%5Cend%7Bpmatrix%7D%20%5Cotimes%20%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%200%20%5Cend%7Bpmatrix%7D%20=%20%5Cbegin%7Bpmatrix%7D%201%20%5Ccdot%201%20%5C%5C%201%20%5Ccdot%200%20%5C%5C%200%20%5Ccdot%201%20%5C%5C%200%20%5Ccdot%200%20%5Cend%7Bpmatrix%7D%20=%20%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%200%20%5C%5C%200%20%5C%5C%200%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A%5C%5C%0A%7C01%5Crangle%20&amp;=%20%7C0%5Crangle%20%5Cotimes%20%7C1%5Crangle%20=%20%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%200%20%5Cend%7Bpmatrix%7D%20%5Cotimes%20%5Cbegin%7Bpmatrix%7D%200%20%5C%5C%201%20%5Cend%7Bpmatrix%7D%20=%20%5Cbegin%7Bpmatrix%7D%201%20%5Ccdot%200%20%5C%5C%201%20%5Ccdot%201%20%5C%5C%200%20%5Ccdot%200%20%5C%5C%200%20%5Ccdot%201%20%5Cend%7Bpmatrix%7D%20=%20%5Cbegin%7Bpmatrix%7D%200%20%5C%5C%201%20%5C%5C%200%20%5C%5C%200%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A%5C%5C%0A%7C10%5Crangle%20&amp;=%20%7C1%5Crangle%20%5Cotimes%20%7C0%5Crangle%20=%20%5Cbegin%7Bpmatrix%7D%200%20%5C%5C%201%20%5Cend%7Bpmatrix%7D%20%5Cotimes%20%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%200%20%5Cend%7Bpmatrix%7D%20=%20%5Cbegin%7Bpmatrix%7D%200%20%5Ccdot%201%20%5C%5C%200%20%5Ccdot%200%20%5C%5C%201%20%5Ccdot%201%20%5C%5C%201%20%5Ccdot%200%20%5Cend%7Bpmatrix%7D%20=%20%5Cbegin%7Bpmatrix%7D%200%20%5C%5C%200%20%5C%5C%201%20%5C%5C%200%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A%5C%5C%0A%7C11%5Crangle%20&amp;=%20%7C1%5Crangle%20%5Cotimes%20%7C1%5Crangle%20=%20%5Cbegin%7Bpmatrix%7D%200%20%5C%5C%201%20%5Cend%7Bpmatrix%7D%20%5Cotimes%20%5Cbegin%7Bpmatrix%7D%200%20%5C%5C%201%20%5Cend%7Bpmatrix%7D%20=%20%5Cbegin%7Bpmatrix%7D%200%20%5Ccdot%200%20%5C%5C%200%20%5Ccdot%201%20%5C%5C%201%20%5Ccdot%200%20%5C%5C%201%20%5Ccdot%201%20%5Cend%7Bpmatrix%7D%20=%20%5Cbegin%7Bpmatrix%7D%200%20%5C%5C%200%20%5C%5C%200%20%5C%5C%201%20%5Cend%7Bpmatrix%7D%0A%5Cend%7Baligned%7D%0A"></p>
<p><strong>General Rule for n-qubits</strong> For an <img src="https://latex.codecogs.com/png.latex?n">-qubit state <img src="https://latex.codecogs.com/png.latex?%7Cx%5Crangle"> where <img src="https://latex.codecogs.com/png.latex?x"> is the decimal representation of the binary string: * The vector has a length of <img src="https://latex.codecogs.com/png.latex?2%5En">. * The vector has a <img src="https://latex.codecogs.com/png.latex?1"> at the <img src="https://latex.codecogs.com/png.latex?x">-th index (starting from 0) and <img src="https://latex.codecogs.com/png.latex?0"> elsewhere.</p>
<p><strong>Mixed Tensor Products (Superposition)</strong> If <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%5Crangle%20=%20%5Calpha%7C0%5Crangle%20+%20%5Cbeta%7C1%5Crangle"> and <img src="https://latex.codecogs.com/png.latex?%7C%5Cphi%5Crangle%20=%20%5Cgamma%7C0%5Crangle%20+%20%5Cdelta%7C1%5Crangle">, then: <img src="https://latex.codecogs.com/png.latex?%0A%7C%5Cpsi%5Crangle%20%5Cotimes%20%7C%5Cphi%5Crangle%20=%20%5Cbegin%7Bpmatrix%7D%20%5Calpha%20%5C%5C%20%5Cbeta%20%5Cend%7Bpmatrix%7D%20%5Cotimes%20%5Cbegin%7Bpmatrix%7D%20%5Cgamma%20%5C%5C%20%5Cdelta%20%5Cend%7Bpmatrix%7D%20=%20%5Cbegin%7Bpmatrix%7D%20%5Calpha%5Cgamma%20%5C%5C%20%5Calpha%5Cdelta%20%5C%5C%20%5Cbeta%5Cgamma%20%5C%5C%20%5Cbeta%5Cdelta%20%5Cend%7Bpmatrix%7D%0A"></p>
<p><strong>Basis Definitions</strong></p>
<ul>
<li><strong>Hadamard Basis (<img src="https://latex.codecogs.com/png.latex?X">-basis):</strong> <img src="https://latex.codecogs.com/png.latex?%7C+%5Crangle%20=%20H%7C0%5Crangle%20=%20%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%201%20%5Cend%7Bpmatrix%7D,%20%5Cquad%20%7C-%5Crangle%20=%20H%7C1%5Crangle%20=%20%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%20-1%20%5Cend%7Bpmatrix%7D"></li>
</ul>
<p><strong>Tensor Products of Basis Vectors</strong> <img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A%5C%5C%0A&amp;%5Ctext%7BHadamard%20($X$-basis):%7D%20&amp;%20%7C++%5Crangle%20&amp;=%20%7C+%5Crangle%20%5Cotimes%20%7C+%5Crangle%20=%20%5Cfrac%7B1%7D%7B2%7D%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%201%20%5C%5C%201%20%5C%5C%201%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A&amp;%20&amp;%20%7C+-%5Crangle%20&amp;=%20%7C+%5Crangle%20%5Cotimes%20%7C-%5Crangle%20=%20%5Cfrac%7B1%7D%7B2%7D%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%20-1%20%5C%5C%201%20%5C%5C%20-1%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A&amp;%20&amp;%20%7C--%5Crangle%20&amp;=%20%7C-%5Crangle%20%5Cotimes%20%7C-%5Crangle%20=%20%5Cfrac%7B1%7D%7B2%7D%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%20-1%20%5C%5C%20-1%20%5C%5C%201%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A&amp;%20&amp;%20%7C-+%5Crangle%20&amp;=%20%7C-%5Crangle%20%5Cotimes%20%7C+%5Crangle%20=%20%5Cfrac%7B1%7D%7B2%7D%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%201%20%5C%5C%20-1%20%5C%5C%20-1%20%5Cend%7Bpmatrix%7D%0A%5Cend%7Baligned%7D%0A"></p>
<p><strong>Mixed Basis States</strong> <img src="https://latex.codecogs.com/png.latex?%7C+%5Crangle%20%5Cotimes%20%7C0%5Crangle%20=%20%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%201%20%5Cend%7Bpmatrix%7D%20%5Cotimes%20%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%200%20%5Cend%7Bpmatrix%7D%20=%20%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%200%20%5C%5C%201%20%5C%5C%200%20%5Cend%7Bpmatrix%7D"></p>
<p><strong>Measurement in the Hadamard Basis</strong> To measure a state <img src="https://latex.codecogs.com/png.latex?%7C%5Cpsi%5Crangle"> in the Hadamard basis using the Born Rule, you project onto the <img src="https://latex.codecogs.com/png.latex?%7C+%5Crangle"> or <img src="https://latex.codecogs.com/png.latex?%7C-%5Crangle"> states: <img src="https://latex.codecogs.com/png.latex?P(+)%20=%20%7C%5Clangle%20+%7C%5Cpsi%5Crangle%7C%5E2,%20%5Cquad%20P(-)%20=%20%7C%5Clangle%20-%7C%5Cpsi%5Crangle%7C%5E2"></p>
<p><strong>11. 2-Qubit Gate Tensor Products</strong> The following matrices represent the operations when gates are applied in parallel to two separate qubits.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Baligned%7D%0A&amp;I%20%5Cotimes%20I%20=%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%200%20&amp;%200%20&amp;%200%20%5C%5C%200%20&amp;%201%20&amp;%200%20&amp;%200%20%5C%5C%200%20&amp;%200%20&amp;%201%20&amp;%200%20%5C%5C%200%20&amp;%200%20&amp;%200%20&amp;%201%20%5Cend%7Bpmatrix%7D%0A&amp;I%20%5Cotimes%20X%20=%20%5Cbegin%7Bpmatrix%7D%200%20&amp;%201%20&amp;%200%20&amp;%200%20%5C%5C%201%20&amp;%200%20&amp;%200%20&amp;%200%20%5C%5C%200%20&amp;%200%20&amp;%200%20&amp;%201%20%5C%5C%200%20&amp;%200%20&amp;%201%20&amp;%200%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A%5C%5C%0A&amp;X%20%5Cotimes%20I%20=%20%5Cbegin%7Bpmatrix%7D%200%20&amp;%200%20&amp;%201%20&amp;%200%20%5C%5C%200%20&amp;%200%20&amp;%200%20&amp;%201%20%5C%5C%201%20&amp;%200%20&amp;%200%20&amp;%200%20%5C%5C%200%20&amp;%201%20&amp;%200%20&amp;%200%20%5Cend%7Bpmatrix%7D%0A&amp;X%20%5Cotimes%20X%20=%20%5Cbegin%7Bpmatrix%7D%200%20&amp;%200%20&amp;%200%20&amp;%201%20%5C%5C%200%20&amp;%200%20&amp;%201%20&amp;%200%20%5C%5C%200%20&amp;%201%20&amp;%200%20&amp;%200%20%5C%5C%201%20&amp;%200%20&amp;%200%20&amp;%200%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A%5C%5C%0A&amp;Z%20%5Cotimes%20Z%20=%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%200%20&amp;%200%20&amp;%200%20%5C%5C%200%20&amp;%20-1%20&amp;%200%20&amp;%200%20%5C%5C%200%20&amp;%200%20&amp;%20-1%20&amp;%200%20%5C%5C%200%20&amp;%200%20&amp;%200%20&amp;%201%20%5Cend%7Bpmatrix%7D%0A&amp;X%20%5Cotimes%20Z%20=%20%5Cbegin%7Bpmatrix%7D%200%20&amp;%200%20&amp;%201%20&amp;%200%20%5C%5C%200%20&amp;%200%20&amp;%200%20&amp;%20-1%20%5C%5C%201%20&amp;%200%20&amp;%200%20&amp;%200%20%5C%5C%200%20&amp;%20-1%20&amp;%200%20&amp;%200%20%5Cend%7Bpmatrix%7D%20%5C%5C%0A%5C%5C%0A&amp;Z%20%5Cotimes%20X%20=%20%5Cbegin%7Bpmatrix%7D%200%20&amp;%201%20&amp;%200%20&amp;%200%20%5C%5C%201%20&amp;%200%20&amp;%200%20&amp;%200%20%5C%5C%200%20&amp;%200%20&amp;%200%20&amp;%20-1%20%5C%5C%200%20&amp;%200%20&amp;%20-1%20&amp;%200%20%5Cend%7Bpmatrix%7D%0A&amp;H%20%5Cotimes%20H%20=%20%5Cfrac%7B1%7D%7B2%7D%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%201%20&amp;%201%20&amp;%201%20%5C%5C%201%20&amp;%20-1%20&amp;%201%20&amp;%20-1%20%5C%5C%201%20&amp;%201%20&amp;%20-1%20&amp;%20-1%20%5C%5C%201%20&amp;%20-1%20&amp;%20-1%20&amp;%201%20%5Cend%7Bpmatrix%7D%0A%5Cend%7Baligned%7D%0A"></p>
<p><strong>12. 3-Qubit Hadamard Tensor Product (<img src="https://latex.codecogs.com/png.latex?H%5E%7B%5Cotimes%203%7D">)</strong> Applying a Hadamard gate to three qubits simultaneously creates a uniform superposition of all 8 possible basis states.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AH%20%5Cotimes%20H%20%5Cotimes%20H%20=%20%5Cfrac%7B1%7D%7B2%5Csqrt%7B2%7D%7D%20%5Cbegin%7Bpmatrix%7D%0A1%20&amp;%201%20&amp;%201%20&amp;%201%20&amp;%201%20&amp;%201%20&amp;%201%20&amp;%201%20%5C%5C%0A1%20&amp;%20-1%20&amp;%201%20&amp;%20-1%20&amp;%201%20&amp;%20-1%20&amp;%201%20&amp;%20-1%20%5C%5C%0A1%20&amp;%201%20&amp;%20-1%20&amp;%20-1%20&amp;%201%20&amp;%201%20&amp;%20-1%20&amp;%20-1%20%5C%5C%0A1%20&amp;%20-1%20&amp;%20-1%20&amp;%201%20&amp;%201%20&amp;%20-1%20&amp;%20-1%20&amp;%201%20%5C%5C%0A1%20&amp;%201%20&amp;%201%20&amp;%201%20&amp;%20-1%20&amp;%20-1%20&amp;%20-1%20&amp;%20-1%20%5C%5C%0A1%20&amp;%20-1%20&amp;%201%20&amp;%20-1%20&amp;%20-1%20&amp;%201%20&amp;%20-1%20&amp;%201%20%5C%5C%0A1%20&amp;%201%20&amp;%20-1%20&amp;%20-1%20&amp;%20-1%20&amp;%20-1%20&amp;%201%20&amp;%201%20%5C%5C%0A1%20&amp;%20-1%20&amp;%20-1%20&amp;%201%20&amp;%20-1%20&amp;%201%20&amp;%201%20&amp;%20-1%0A%5Cend%7Bpmatrix%7D%0A"></p>
<p><strong>13. General n-qubit Identity and Parity</strong> * <strong><img src="https://latex.codecogs.com/png.latex?I%5E%7B%5Cotimes%20n%7D">:</strong> An identity matrix of size <img src="https://latex.codecogs.com/png.latex?2%5En%20%5Ctimes%202%5En">. * <strong><img src="https://latex.codecogs.com/png.latex?Z%5E%7B%5Cotimes%20n%7D">:</strong> A diagonal matrix where the entry is <img src="https://latex.codecogs.com/png.latex?+1"> if the basis state has an even number of <img src="https://latex.codecogs.com/png.latex?1">s and <img src="https://latex.codecogs.com/png.latex?-1"> if it has an odd number of <img src="https://latex.codecogs.com/png.latex?1">s.</p>
<p><strong>14. Entanglement: The 4 Bell States</strong></p>
<p>The Bell states (or EPR pairs) are the four maximally entangled two-qubit states. They form an orthonormal basis for the 4-dimensional Hilbert space of two qubits.</p>
<p><strong>Generating Bell States via Circuit</strong> The general recipe to create a Bell state from a basis state <img src="https://latex.codecogs.com/png.latex?%7Cxy%5Crangle"> is: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BBell%7D(x,y)%20=%20%5Ctext%7BCNOT%7D_%7B0%20%5Cto%201%7D%20(H%20%5Cotimes%20I)%20%7Cxy%5Crangle"></p>
<p><strong>Matrix of the CNOT Gate</strong> The CNOT gate flips the target (second) qubit if the control (first) qubit is <img src="https://latex.codecogs.com/png.latex?%7C1%5Crangle">: <img src="https://latex.codecogs.com/png.latex?%5Ctext%7BCNOT%7D%20=%20%5Cbegin%7Bpmatrix%7D%201%20&amp;%200%20&amp;%200%20&amp;%200%20%5C%5C%200%20&amp;%201%20&amp;%200%20&amp;%200%20%5C%5C%200%20&amp;%200%20&amp;%200%20&amp;%201%20%5C%5C%200%20&amp;%200%20&amp;%201%20&amp;%200%20%5Cend%7Bpmatrix%7D"></p>
<p><strong>The Four Bell States</strong></p>
<table class="table">
<colgroup>
<col style="width: 33%">
<col style="width: 33%">
<col style="width: 33%">
</colgroup>
<thead>
<tr class="header">
<th style="text-align: left;">Initial State</th>
<th style="text-align: left;">Bell State Notation</th>
<th style="text-align: left;">Vector / Formula</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%7C00%5Crangle"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%7C%5CPhi%5E+%5Crangle"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D(%7C00%5Crangle%20+%20%7C11%5Crangle)%20=%20%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%200%20%5C%5C%200%20%5C%5C%201%20%5Cend%7Bpmatrix%7D"></td>
</tr>
<tr class="even">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%7C10%5Crangle"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%7C%5CPhi%5E-%5Crangle"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D(%7C00%5Crangle%20-%20%7C11%5Crangle)%20=%20%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D%5Cbegin%7Bpmatrix%7D%201%20%5C%5C%200%20%5C%5C%200%20%5C%5C%20-1%20%5Cend%7Bpmatrix%7D"></td>
</tr>
<tr class="odd">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%7C01%5Crangle"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%7C%5CPsi%5E+%5Crangle"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D(%7C01%5Crangle%20+%20%7C10%5Crangle)%20=%20%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D%5Cbegin%7Bpmatrix%7D%200%20%5C%5C%201%20%5C%5C%201%20%5C%5C%200%20%5Cend%7Bpmatrix%7D"></td>
</tr>
<tr class="even">
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%7C11%5Crangle"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%7C%5CPsi%5E-%5Crangle"></td>
<td style="text-align: left;"><img src="https://latex.codecogs.com/png.latex?%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D(%7C01%5Crangle%20-%20%7C10%5Crangle)%20=%20%5Cfrac%7B1%7D%7B%5Csqrt%7B2%7D%7D%5Cbegin%7Bpmatrix%7D%200%20%5C%5C%201%20%5C%5C%20-1%20%5C%5C%200%20%5Cend%7Bpmatrix%7D"></td>
</tr>
</tbody>
</table>
<p>*Of most of which was generated by Gemini [3]</p>
<p>It is also possible to visualize the equations in LaTeX using the draw method of Statevector object in Qiskit. For example:</p>
<div id="e7987d87-7bfa-4585-a5b4-e60c2b12afad" class="cell" data-execution_count="2">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> qiskit.quantum_info <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Statevector</span>
<span id="cb2-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> qiskit <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> QuantumCircuit</span>
<span id="cb2-3"></span>
<span id="cb2-4">qc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> QuantumCircuit(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb2-5">qc.x(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb2-6">qc.h(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb2-7">qc.z(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb2-8">psi <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Statevector(qc)</span>
<span id="cb2-9">psi.draw(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"latex"</span>)</span></code></pre></div>
</details>
<div class="cell-output cell-output-display cell-output-markdown" data-execution_count="2">
<p><img src="https://latex.codecogs.com/png.latex?%5Cfrac%7B%5Csqrt%7B2%7D%7D%7B2%7D%20%7C00%5Crangle+%5Cfrac%7B%5Csqrt%7B2%7D%7D%7B2%7D%20%7C10%5Crangle"></p>
</div>
</div>
</section>
<section id="p1-q3" class="level3">
<h3 class="anchored" data-anchor-id="p1-q3">3. <em>How did you get started running your first quantum circuits using IBM Qiskit and Xanadu Pennylane Jupyter Notebook platforms?</em></h3>
<p>I first started checking out Qiskit in the labs and seeing how it generates the circuits in the IBM Quantum Composer. As for PennyLane, one of the other students said that the PennyLane Codebook was helpful in learning PennyLane and comprehension off the material. So, I have since completed the Introduction segment, but I plan to continue to follow along [4].</p>
</section>
<section id="p1-q4" class="level3">
<h3 class="anchored" data-anchor-id="p1-q4">4. <em>How would you motivate other students to join the journey into quantum computing given the motivational materials presented in class and found in the references? Your answers to this question will likely evolve during this course. Revisit regularly this quesion.</em></h3>
<p>Well, I have already suggested to my friend, who is interested in the material but couldn’t join the course, that he should check out the content on PennyLane and go through the CodeBook. There are also the tutorials available on the IBM Qiskit website [5].</p>
<p>Also, suggesting the Bloch Sphere is sometimes a good tool for visualizing phase changes and the relative locations of the basis states; however, it is not an accurate tool, as the basis kets are intended to orthogonal, but instead are viewed as opposing in the Bloch Sphere.</p>
<p>The short article about Quantum and Computational Chemistry was insightful and approachable [6]. I would recommend that.</p>
<p>From my understanding, Quantum Computing is inevitable and will become a common way for sophisticated problem in the not-too-distant future. Therefore it would be advised that everyone in Software Engineering and Computer Science start to understand at least the basics of Quantum Computing. Take this article “Quantum Computing Moves from Theoretical to Inevitable” that explains the upcoming markets that will benefit the most from Quantum Computing [7].</p>
</section>
<section id="p1-q5" class="level3">
<h3 class="anchored" data-anchor-id="p1-q5">5. <em>Which algorithm is your favourite quantum algorithm so far?</em></h3>
<p>I think that all the algorithms, so far, are interesting. The most difficult, yet intriguing, part is trying to grasp the significance of how gates modify the quantum state and how the math verifies the expected results in the end.</p>
<p>From a curiosity perspective, I would say that the Teleportation algorithm is the most important because it proves the ability to move quatum states around, and it also kills the misconception that many people have, that Quantum states can somehow transfer information faster than the speed of light.</p>
<p>I have included a snippiet of code that simulates transportation. It was completed with the aid of Gemini [3].</p>
<div id="6bad5897-0cc5-4645-891b-28b380ae85dc" class="cell" data-execution_count="3">
<details class="code-fold">
<summary>Show code</summary>
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pennylane <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> qml</span>
<span id="cb3-2"></span>
<span id="cb3-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># We need 3 wires for teleportation</span></span>
<span id="cb3-4">dev <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> qml.device(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"default.qubit"</span>, wires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb3-5"></span>
<span id="cb3-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@qml.qnode</span>(dev)</span>
<span id="cb3-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-style: inherit;">def</span> teleportation_circuit():</span>
<span id="cb3-8">    </span>
<span id="cb3-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. PREPARE THE STATE TO TELEPORT (on wire 0)</span></span>
<span id="cb3-10">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Let's just create a random state using a rotation</span></span>
<span id="cb3-11">    qml.RX(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.23</span>, wires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb3-12">    qml.RY(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.45</span>, wires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb3-13"></span>
<span id="cb3-14">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. CREATE ENTANGLEMENT (between Alice/wire 1 and Bob/wire 2)</span></span>
<span id="cb3-15">    qml.Hadamard(wires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb3-16">    qml.CNOT(wires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span>
<span id="cb3-17"></span>
<span id="cb3-18">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 3. ALICE'S OPERATIONS (Bell State Measurement)</span></span>
<span id="cb3-19">    qml.CNOT(wires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb3-20">    qml.Hadamard(wires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb3-21"></span>
<span id="cb3-22">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 4. MEASURE AND CONDITIONALLY APPLY CORRECTIONS</span></span>
<span id="cb3-23">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># In PennyLane, we use m_0 and m_1 to represent Alice's measurement results</span></span>
<span id="cb3-24">    m_0 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> qml.measure(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb3-25">    m_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> qml.measure(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb3-26"></span>
<span id="cb3-27">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Bob applies corrections based on Alice's classical bits</span></span>
<span id="cb3-28">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># If m_1 is 1, apply PauliX; if m_0 is 1, apply PauliZ</span></span>
<span id="cb3-29">    qml.cond(m_1, qml.PauliX)(wires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb3-30">    qml.cond(m_0, qml.PauliZ)(wires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb3-31"></span>
<span id="cb3-32">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return the probabilites in the state</span></span>
<span id="cb3-33">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">return</span> qml.probs(wires<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb3-34"></span>
<span id="cb3-35"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Execute</span></span>
<span id="cb3-36">result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> teleportation_circuit()</span>
<span id="cb3-37"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(result)</span></code></pre></div>
</details>
<div class="cell-output cell-output-stdout">
<pre><code>[0.6504817 0.3495183]</code></pre>
</div>
</div>
</section>
<section id="p1-q6" class="level3">
<h3 class="anchored" data-anchor-id="p1-q6">6. <em>What was the most challenging part in understanding Grover’s algorithm?</em></h3>
<p>I don’t think we have covered Grover’s algorithm yet in class, but I looked it up and this PennyLane article covers it pretty well [8].</p>
<p>I suppose one of the most challenging parts of using Grover’s algorithm or any other Oracle based algorithm is being able to imagine and then describe how the oracle needed for the specific problem.</p>
</section>
<section id="p1-q7" class="level3">
<h3 class="anchored" data-anchor-id="p1-q7">7. <em>Required: What are your personal insights, aha moments, and epiphanies you experienced in the first part of this course?</em></h3>
<p>Some things that ocurred to me were:</p>
<ul>
<li><p>The matrix math becomes unwieldy very quickly, and that Dirac notation is much preferred.</p></li>
<li><p>Quantum computing in inevitable</p></li>
<li><p>The algorithms needed for solving a modern problem must be huge (many quibits, many gates) with large portions being progromatically generated or transpiled.</p></li>
<li><p>Modern Quantum Computing is the culmination of many very clever people.</p></li>
<li><p>Quantum computing will not likely be of much use alone but will be integrated wtih standard computing; something that can be called upon when the certain cases arise (such as with simulation or searching).</p></li>
</ul>
</section>
<section id="p1-q8" class="level3">
<h3 class="anchored" data-anchor-id="p1-q8">8. <em>Required: How did you experience Generative AI as a learning tool for this course?</em></h3>
<p>Gen AI, especially Google Gemini, has been extremely helpful in this course. I would say that Gen AI is helpful in a many scenarios, but academically, it has been essential for easing the initial learning curve involved with such things as Dirac notation and explaining phase rotation. The optimist in me says that AI is a super useful tool that has come along at a time when it is most in need where we can all benefit from the culmination of our efforts. The pessimist in me says that all the most useful AI models will be behind paywalls soon enough and we may find ourselves reliant on them, especially if we don’t actually understand the information that it gives back to us. So, ultimately, GenAI is amazing for boiler-plate work, but for knowledge work (exploratory solutions and the like), the results should still be critisized and the technicalites understood.</p>
</section>
<section id="p1-q9" class="level3">
<h3 class="anchored" data-anchor-id="p1-q9">9. <em>Record your Generative AI prompts and contexts for Basic Quantum Terms, Complex Linear Algebra, Quantum Algorithms, Python, Qiskit, and PennyLane inquiries for easy recall. Use the same line item or project in your genAI engine (e.g., ChatGPT, Google Gemini, Perplexity, or others) to build up the “quantum context”.</em></h3>
<p>“Hey can you explain superposition, entanglement, and the no cloning theorem? keep it simple and just tell me why each one actually matters for making a quantum computer faster than a regular one.”</p>
<p>“Quantum states use a lot of linear algebra. Can you explain how bra ket notation works with unitary matrices and hermitian operators. Also, why does a unitary matrix have to keep the total probability at 1 when it acts on a qubit state?”</p>
<p>“Can you explain to me how Grover’s algorithm works? I would like the Dirac and Matrix representation.”</p>
<p>“I need to make a bell state in qiskit. Can you give me the python code to set up 2 qubits, apply them with a hadamard and a cnot, and then run it to see the results. keep the code simple and just use comments to say which qubit is which.”</p>
<p>“I want to try a teleportation circuit in pennylane. Can you show me a template for that? Please explain the different steps.”</p>
</section>
</section>
<section id="part-1-bibliography" class="level2">
<h2 class="anchored" data-anchor-id="part-1-bibliography"><strong>Part 1 Bibliography</strong></h2>
<p>[1] GeeksforGeeks, “Matrix Operations,” GeeksforGeeks, Nov.&nbsp;23, 2020. https://www.geeksforgeeks.org/maths/matrix-operations/<br>
[2] “Matrix Calculator - Reshish,” matrix.reshish.com. https://matrix.reshish.com/<br>
[3] Google, “Gemini,” gemini.google.com, 2025. https://gemini.google.com/app<br>
[4] “Map | PennyLane Codebook,” Pennylane.ai, 2025. https://pennylane.ai/codebook/learning-paths<br>
[5] “IBM Quantum Computing | Qiskit,” Ibm.com, 2026. https://www.ibm.com/quantum/qiskit#tutorials (accessed Feb.&nbsp;12, 2026).<br>
[6] “Fertilizer and other quantum computer chemistry,” Quantum Flagship. https://qt.eu/applications/fertilizer-and-other-quantum-computer-chemistry<br>
[7] G. Dunn, V. Sinha, Laurent-Pierre Baculard, S. Ali, and W. Chang, “Quantum Computing Moves from Theoretical to Inevitable,” Bain, Sep.&nbsp;23, 2025. https://www.bain.com/insights/quantum-computing-moves-from-theoretical-to-inevitable-technology-report-2025/<br>
[8] L. Botelho, “Grover’s Algorithm,” PennyLane Demos, Jul.&nbsp;03, 2023. https://pennylane.ai/qml/demos/tutorial_grovers_algorithm</p>
</section>
<section id="part-2" class="level2">
<h2 class="anchored" data-anchor-id="part-2"><strong>Part 2: Documenting my Quantum Journey</strong></h2>
<section id="p2-q1" class="level3">
<h3 class="anchored" data-anchor-id="p2-q1">1. <em>In your own words, describe the Quantum Fourier Transform (QFT) algorithm. How is QFT used in quantum computing?</em></h3>
<p>The Quantum Fourier Transform is the quantum analog for the traditional Fourier Transform algorithm. A generalization of the the Fourier transform can utilize the Euclidean space to allow for easy manipulations of qubits. Superposition, entanglement, and amplitude amplification working together in this algorithm allows for exponential speed-up. It effectivley maps a quantum state’s amplitude distribution from the computational basis to the phase basis. Because of this, a QFT is usually followed by the inverse to get useful measurements.[1]</p>
<p>QFT usually consists of a Hadamard transform, to create equal superposition, then phase shifts are applied to encode the frequency components. [1]</p>
<p>It is prodominantly used Shor’s Algorithm, Quantum Phase Estimation, and Quantum Machine Learning. [1]</p>
</section>
<section id="p2-q2" class="level3">
<h3 class="anchored" data-anchor-id="p2-q2">2. <em>In your own words, describe the Quantum Phase Estimation (QPE) algorithm. How is QPE used in quantum computing?</em></h3>
<p>Quantum Phase Estimation tackles a problem that is at the basis of quantum computing. How can we know the phase of a quantum system if when we measure a qubit directly, the superposition and phase immediately collapses. So, the QPE is able to transfer the phase using “phase kickback” to different, counting qubits, that can be applied to the inverse QFT to then be measured. [2]</p>
<p>QPE usually consists of putting the counting qubits in superposition and the using Controlled-U gates to kick back the phase. Then the inverse QFT is applied to the counting register. The measurement is a bitstring representation of the phase in binary. [2]</p>
<p>QPE is used in Shor’s algorithm, quantum simulation, and solving linear systems. [2]</p>
<p>QPE is primarily theoretical at the moment as current implimentations are hardware intensive. [2]</p>
</section>
<section id="p2-q3" class="level3">
<h3 class="anchored" data-anchor-id="p2-q3">3. <em>For you, what was the most challenging part of understanding Grover’s algorithm and why?</em></h3>
<p>For me, the most difficult part of understanding Grover’s algorithm, as with most of the algorithms is understanding how the “phase kickback” works and implementing it. Otherwise, I understand pretty well how the Oracle and the Diffusion Operator work in tandem to isolate and highlight the “hidden” result.</p>
</section>
<section id="p2-q4" class="level3">
<h3 class="anchored" data-anchor-id="p2-q4">4. <em>Which is your favourite quantum algorithm and why?</em></h3>
<p>I still don’t know if I am educated enough to make this statement, yet, but my ideAL algorithm would be one where I could solve a real world problem with the existing technology and real qubits in a way that shows temporal or computational complexity impro vements over a classical calculation.</p>
</section>
<section id="p2-q5" class="level3">
<h3 class="anchored" data-anchor-id="p2-q5">5. <em>What is the role of eigenvalues and eigenstates (eigenvectors) in quantum computing?</em></h3>
<p>They remove a lot of complexities in the computations. Instead of dealing with entire matrices, you can instead create the results with eigen values as scalars, and eigen vectors together as matrices.</p>
<p>All observable quantities, in quantum computing, can be represented by Hermitian operators and the results that come from measurements of these quantities are the eigenvalues of the operators. The eigenstates are then the “stable” configurations of the operators.</p>
<p>A superposition can be seen as a linear combination of several eigenstates.</p>
</section>
<section id="p2-q6" class="level3">
<h3 class="anchored" data-anchor-id="p2-q6">6. <em>Summarize the decomposition strategies presented in class for developing hybrid quantum-classical systems.</em></h3>
<p><strong>Phase Oracles</strong></p>
<p>The phase oracle is a black-box function that recognize the solution in the solution space and changes the phase of this solution. It goes -&gt; Define the logic, initialize the Ancilla, Flip the solution phase in the solution space, Reverse initialization logic. [3]</p>
<p><strong>QUBO/HUBO</strong></p>
<p>Creating a QUBO is translating Constraints into Energy where the “correct” answer is the lowest possible value in a quadratic equation. It goes -&gt; Start with constraints, turn them into penalties, simplify to binary variables, map result to Quantum gates Z and I and scalars.</p>
</section>
<section id="p2-q7" class="level3">
<h3 class="anchored" data-anchor-id="p2-q7">7. <em>Which one is your favourite decomposition strategy? Describe this strategy in detail.</em></h3>
<p>Well, they are all quite difficult to derive, but I think that the QUBO strategy of problem decomposition provides the most promising results especially with the hardware focus that the local D-Wave lab provides. The algorithm for mapping the problems to a Quadratic Unconstrained Binary Optimization problem open the door to a bunch of possiblities when designing quantum algorthims for existing and novel software problems.</p>
</section>
<section id="p2-q8" class="level3">
<h3 class="anchored" data-anchor-id="p2-q8">8. <em>Write a summary of the different quantum applications presented by the graduate students.</em></h3>
<p><strong>Protein Folding</strong><br>
Naomi Phan - Protein Structure Folding</p>
<p>Naomi explores the world of protein folding and how amazingly complex (with regard to amino acid rotations and permutations). “Brute Force for 1 protein takes longer than the age of the universe”. Naomi uses a Variational Quantum Eigensolver mixed with a classical optimizer to employ the quantum advantage.</p>
<p><strong>Route Planning</strong> (2 different students)<br>
Aden Knelson-Dobson - Quantum Traffic Flow Optimization</p>
<p>Aden showed that a traffic flow optimization problem can be formulated as QUBO and thus could be aplicable to be solved with quantum annealing. Papers referenced are Lucas (2014) and Neukart et al.&nbsp;(2017).</p>
<p>Joyce can de Vegte - Quantum Traffic Optimization</p>
<p>Joyce explored the trafic optimization problem while giving a clear explanation of how to create the cost Hamiltionian and using QAOA with 1 and 2 layers. Namely, A. Giovagnoli’s “An Introduction to the Quantum Approximate Optimization Algorithm” was referenced.</p>
<p><strong>graph colouring</strong><br>
Chuan Zhang - Graph Coloring Using QAOA</p>
<p>Chuan explains how Grover’s algorithm is not a great choice because of the large amount of hardware resources need. He instead goes onto suggest that a QUBO and QAOA is a better approach. After comparison between algorithm types, it is shown that RQAOA is the best contender for solving this type of problem.</p>
<p><strong>quantum encryption</strong><br>
Juliiana Unesikhina - A Study of Encrypted Quantum State Distribution</p>
<p>Juliiana discusses the challenges of distributing quantum tasks, and how these limitations actually become opportunities. She highlights why we should strive for Quantum State Distribution with several references.</p>
<p>[4]</p>
</section>
<section id="p2-q9" class="level3">
<h3 class="anchored" data-anchor-id="p2-q9">9. <em>Which applications inspired you the most? Describe this application in more detail. Please note graduate students who have presented an application cannot write about the application they present for their grad project.</em></h3>
<p>I definitely think that the presentations on route finding were the most intriguing as I am working on a Trip Planner application at the moment to demonstrate on my personal website. I will also have a section dedicated to discussion of quantum applcations and how they can be used in my software. So, I find these presentations, not only easy to understand, because I feel that everyone is more or less domain familiar, but it can also be potentially rolled out in my application in the near future.</p>
</section>
<section id="p2-q10" class="level3">
<h3 class="anchored" data-anchor-id="p2-q10">10. <em>Did you use Generative AI tools (e.g., ChatGPT, Gemini, Copilot, or Perplexity) in the learning journey of this course? If so, what was your experience?</em></h3>
<p>Yes, I used them plenty. Mostly Gemini for this kind of content. I thought that it did a pretty good job and dumbing difficult topics down for this layperson.</p>
<p>I find that you have to use the AI conscientiously. You have to consider resources, ask for citations, compare against other LLMs and even word of mouth to ensure that what you are propogating is correct and not a hallucination of the AI.</p>
<p>I think generally, AI will excelerate all facets of research, exploration, and study, but like not always clicking the first link on Google, or assuming the float representing a rational number from a program is going to be correct, you should not assume that the first response from AI is correct.</p>
</section>
<section id="p2-q11" class="level3">
<h3 class="anchored" data-anchor-id="p2-q11">11. <em>What topics, methods, and tools of this course did you add already or are you going to add to your résumé?</em></h3>
<p>I am going to add many things to my protfolio website including this document here. For my resume, I think I will add that I understand the basics, but I plan to continue to look into Quantum Algorithms.</p>
</section>
<section id="p2-q12" class="level3">
<h3 class="anchored" data-anchor-id="p2-q12">12. <em>What have been your personal insights, aha moments, or epiphanies you experienced in the second part of your quantum learning journey?</em></h3>
<p>We are here. This is it. The Quantum revolution is coming, but it will not be easy, and as it stands, each algorithm is complex and specifc to each problem, but it has room to emply the quantum advantage. I forsee that there will be libraries (like there are now) and a level of generalization that will make it easy it for quantum software engineers and compilers to create the highest-level algorithms to ping (I think local quantum computers will be reserved for the utmost secure and wealthy) for solutions over the quantum web that solve problems that traditional computers simply cannot solve.</p>
</section>
</section>
<section id="part-2-bibliography" class="level2">
<h2 class="anchored" data-anchor-id="part-2-bibliography"><strong>Part 2 Bibliography</strong></h2>
<p>[1] https://www.quera.com/glossary/quantum-fourier-transform [2] https://www.quera.com/glossary/quantum-phase-estimation [3] https://gemini.google.com/app [4] Relevant, grad-student made presentations from the SEng 457 course BrightSpace page.</p>


</section>
</section>

 ]]></description>
  <category>quantum</category>
  <category>course work</category>
  <category>pennylane</category>
  <guid>https://notes.zakacat.ca/notebooks/TPP-P2-Zak-Toews.html</guid>
  <pubDate>Sun, 08 Mar 2026 00:00:00 GMT</pubDate>
</item>
<item>
  <title>CORDIC Optimization on an STM32 (ARM Cortex-M4)</title>
  <dc:creator>Zak Toews, Robert Bell</dc:creator>
  <link>https://notes.zakacat.ca/notebooks/CORDIC-Optimization-STM32.html</link>
  <description><![CDATA[ 




<center>
<section id="cordic-optimization-project-using-an-stm32-board" class="level1">
<h1><strong>CORDIC Optimization Project using an STM32 Board</strong></h1>
<section id="seng-440-embedded-systems-university-of-victoria-electrical-and-computer-engineering" class="level3">
<h3 class="anchored" data-anchor-id="seng-440-embedded-systems-university-of-victoria-electrical-and-computer-engineering">SENG 440 Embedded Systems — University of Victoria, Electrical and Computer Engineering</h3>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image1.png" class="img-fluid" width="180"></p>
<p>Summer 2025 · Instructor: Mihai Sima · Students: Robert Bell and Zak Toews · Group 18</p>
</section></section></center>

<section id="abstract" class="level2">
<h2 class="anchored" data-anchor-id="abstract">Abstract</h2>
<p>This project presents a fixed-point implementation of the CORDIC algorithm for trigonometric computation on a selected microcontroller using an ARM Cortex-M4. The CORDIC algorithm is an efficient method of computation which allows a resource constrained piece of hardware to perform otherwise costly calculations by replacing multiplication and division operations with shift and add operations, which is preferred on systems without FPUs. We were able to explore and utilize different embedded systems optimization techniques to reduce the number of cycles of computation to achieve a result within acceptable specifications. After each implementation technique was applied, we made sure to use the ARM debug architecture to monitor the number of cycles, and we explored the assembly code to understand the resulting changes in the instructions. Implementing a precalculated look up table (LUT), loop unrolling, and register keywords reduced the number of cycles needed for calculation, while techniques such as CMSIS and predicate replacement over branches reduced overall efficiency. The resulting optimized code saw a reduction of cycle count from ~632, from the math library function, and ~982, from the non-optimized CORDIC function to ~184 cycles. This is a substantial improvement that compares directly with “O3” and “Ofast” optimizations upon the non-optimized CORDIC function.</p>
</section>
<section id="table-of-contents" class="level2">
<h2 class="anchored" data-anchor-id="table-of-contents">Table of Contents</h2>
<ol type="1">
<li>Introduction</li>
<li>Background</li>
<li>Algorithm Design</li>
<li>C Code + Optimization
<ul>
<li>Using <code>register</code> Key Word</li>
<li>Loop Unrolling</li>
<li>CMSIS-DSP Intrinsics</li>
<li>Branch Elimination via Predicated Operations</li>
<li>Replacing Z-Table Calculation with Pre-Initialized Values</li>
</ul></li>
<li>Compiling C and Comparing Assembly</li>
<li>Results</li>
<li>Improvements</li>
<li>Conclusions</li>
<li>References</li>
<li>Appendices</li>
</ol>
</section>
<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>The goal of this design project is to explore methodologies to optimize the CORDIC mathematical technique on a specific microcontroller. We have decided to use the STM32F407G-DISC1 board, which uses a STM32F407VGT6UAA286 chip.</p>
<p>The development of this project was done using the Ubuntu 24.04.2 LTS linux environment on a designated laptop, using the STM32CubeIDE version 1.18.1 integrated development environment. The code was compiled using the GNU Arm Embedded Toolchain (arm-none-eabi-gcc 13.3.rel1). A mesh VPN network was implemented for the developers to access the development computer remotely.</p>
<p>The primary objective of this work was to improve execution speed while preserving the numerical precision of the CORDIC algorithm. As such, the primary success metric was the reduction in clock cycles required for computation.</p>
<p>For reference, calling the standard <code>atan()</code> function from the C math library required approximately 630 clock cycles on the target platform. In comparison, the baseline CORDIC arctangent implementation, as described in the course documentation, required roughly 982 cycles.</p>
<p>A sequence of targeted optimizations was applied to the CORDIC implementation, each tested independently. These efforts culminated in a “naive” optimized version achieving a reduced runtime of approximately 387 cycles.</p>
<p>Further performance gains were observed through inspection of compiler behavior at the <code>-O3</code> optimization level, resulting in a function execution time of approximately 184 cycles — comparable to results achieved with both <code>-O3</code> and <code>-Ofast</code> compiler optimizations.</p>
<p>In addition to these optimizations, several other avenues for potential improvement were identified and evaluated for future work.</p>
<table class="table">
<colgroup>
<col style="width: 50%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th>Zak Toews</th>
<th>Robert Bell</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Implemented “register” keyword optimization · Implemented CMSIS optimization · Implemented loop unrolling optimization · Implemented naive optimization · Implemented final optimization · Report contributions · Presentation contributions</td>
<td>Researched hardware capabilities and available ARM intrinsics · Implemented precalculated LUT · Implemented control flow optimization with predicates · Initialized testbench with DWT and SWO · Report contributions · Presentation contributions</td>
</tr>
</tbody>
</table>
<p><em>Figure 1. Project Contribution Table.</em></p>
</section>
<section id="background" class="level2">
<h2 class="anchored" data-anchor-id="background">Background</h2>
<p><em>(The background section covers the basics about CORDIC: why it is necessary, how it is implemented, its history and applications.)</em></p>
<p>The CORDIC technique has been used in many different applications. The implementation of many mathematical expressions including trigonometric, exponential, and logarithmic functions are often approximated using Taylor series polynomial expansions. These operations provide good approximations to many functions, but can be computationally expensive on hardware, especially on hardware without a floating point unit (FPU), a specialized part of the CPU or separate chip.</p>
<p>This technique relies on two different modes of application, rotation mode and vector mode. The vectoring mode starts with a vector, and makes iterations to rotate that vector toward the x-axis, which allows for the arctan and scaled magnitude to be found. In rotation mode, a vector and an angle are the inputs, and the algorithm rotates that vector by that angle to produce new coordinates, which can be used to compute sine and cosine.</p>
<p>The CORDIC algorithm computes these expensive expressions using only shifts, adds, and a small look up table (LUT). This allows a less expensive calculation to approximate these expressions, which lets machines with limited resources be able to perform such calculations.</p>
<p>CORDIC was developed by Convair, an American aircraft manufacturing company, as a means of digitizing the analog resolvers, the technology used at the time to assist in navigational computation on their aircraft.</p>
<p>Here are some real world applications:</p>
<p><strong>Wireless Communications</strong> CORDIC is extensively used in digital signal processing for wireless systems:</p>
<ul>
<li>Digital down-conversion: Converting high-frequency signals to baseband requires sine/cosine generation for mixing operations</li>
<li>Phase-locked loops (PLLs): CORDIC generates the reference signals needed for frequency synthesis and phase tracking</li>
<li>QAM demodulation: Quadrature amplitude modulation requires precise phase calculations that CORDIC handles efficiently</li>
<li>Beamforming: Antenna arrays use CORDIC for calculating the phase shifts needed to steer transmission beams</li>
</ul>
<p><strong>Graphics and Gaming</strong> Vector rotations are core to 3D graphics:</p>
<ul>
<li>3D transformations: Rotating objects in 3D space, camera movements, and perspective projections</li>
<li>Game physics: Calculating trajectories, collisions, and object orientations</li>
<li>Image processing: Rotating images, geometric corrections, and filtering operations</li>
</ul>
<p><strong>Navigation and Control Systems</strong></p>
<ul>
<li>GPS receivers: CORDIC calculates satellite positions and user location from trigonometric relationships</li>
<li>Inertial navigation: Processing gyroscope and accelerometer data to determine orientation and position</li>
<li>Robotics: Calculating joint angles, end-effector positions, and trajectory planning</li>
</ul>
<p><strong>Digital Signal Processing Hardware</strong> CORDIC is particularly valuable in FPGA and DSP implementations because:</p>
<ul>
<li>It only requires additions, subtractions, and bit shifts (no multipliers)</li>
<li>It’s highly parallelizable and pipeline-friendly</li>
<li>It provides consistent execution time regardless of input values</li>
</ul>
<p><strong>How it works</strong></p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode c code-with-copy"><code class="sourceCode c"><span id="cb1-1">x_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x_i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-2">y_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-3">z_temp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">for</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/* 15 iterations are needed */</span></span>
<span id="cb1-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">if</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>y_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb1-7">        x_temp_2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>y_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">);</span></span>
<span id="cb1-8">        y_temp_2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>x_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">);</span></span>
<span id="cb1-9">        z_temp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> z_table<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">];</span></span>
<span id="cb1-10">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-style: inherit;">else</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb1-11">        x_temp_2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>y_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">);</span></span>
<span id="cb1-12">        y_temp_2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>x_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">);</span></span>
<span id="cb1-13">        z_temp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-=</span> z_table<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">];</span></span>
<span id="cb1-14">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb1-15">    x_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x_temp_2<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-16">    y_temp_1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_temp_2<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-17"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div>
<p><em>Figure 0.0: cordic_arctan.c as described in slide deck (more or less)</em></p>
<p>The CORDIC algorithm uses a fixed set of elementary angles, referred to in this project as a Z-table. The values of such table are calculated as:</p>
<p><img src="https://notes.zakacat.ca/notebooks/{IMG}/image2.png" class="img-fluid"> <img src="https://notes.zakacat.ca/notebooks/{IMG}/image3.png" class="img-fluid"></p>
<p><em>Figure 2. Precomputed arctangent values for CORDIC iterations, adapted from [1].</em></p>
</section>
<section id="algorithm-design" class="level2">
<h2 class="anchored" data-anchor-id="algorithm-design">Algorithm Design</h2>
<p><em>(In the algorithm design section, the details of the dataflow are presented, including details such as register use, bitwidth of variables, and the decisions involving rounding.)</em></p>
<p>Some information that applies to all of our optimization functions:</p>
<p>The input and output of the functions are the 32-bit integer representations of 64-bit double values. Initial x and y double values declared in the main() function are converted into their 32-bit integer representations, then the output z, in our case the result of the arctan(x/y), which is a 32-bit integer, is then converted back to 64-bit double inside the main() function.</p>
<p>The main() function is then used to initialize x and y values, z_table values, and retrieve arctan output (z) values. And for the purposes of testing and confirmation, main also counts the amount of cycles for each optimized function call as well as printing out the result to ensure that the implementation is correct.</p>
<p>It should also be mentioned at this point, that within our initial CORDIC documentation, both arctan and a sin/cos combined function were discussed, but as these functions operate very similarly on an instruction level, only optimizations were applied to the CORDIC arctan function.</p>
<p><strong>Initial Code Design (cordic_arctan.c)</strong></p>
<p>The initial code design used int for all variables. int variables assume the word size of the controller, and in our case that resolves to a signed 32 bit integer. Function input includes int X param, int Y param, int[] Z_table, and int* Z which is a pointer to the final output of the function. Temporary variables are used to accumulate the x, y, and z variables.</p>
<p>After initializing local variables, a loop is called which contains a single decision branch applying an addition or subtraction to the z (output) from the z_table values.</p>
<p>The register keyword was not used, it was assumed before compiling that the local variables would be stored in memory.</p>
<p><strong>Register Code Design (cordic_register_arctan.c)</strong></p>
<p>This function design is the exact same as the initial code design except the local variables use the register keyword. This does not guarantee that the compiler will reserve the registers, but is merely a suggestion. Storing the local variables, that is, everything needed in the function besides the z_table, inside registers will save costly load and store operations.</p>
<p><strong>Unroll Code Design (cordic_arctan_unroll2.c)</strong></p>
<p>This function also starts with the initial code implementation, but within the loop, that previously iterated 15 times, we now have a single loop unroll that results in 7 iterations in a loop and a final iteration outside the loop (due to 15 being an odd number). This not only saves on the loop overhead that is called each iteration, but it also can facilitate pipelining.</p>
<p><strong>CMSIS Code Design (cordic_arctan_CMSIS.c)</strong></p>
<p>This code design is a little bit different when it comes to the initial variables. Instead of having x and y as 32-bit integer representations, they are instead converted to 16-bit integer representations. The local variables then become a 32-bit int of which x and y are packed into, a local z variable, as well as an x and y temp variable for when the 32-bit x/y variable gets unpacked each iteration of the loop. 16-bit addition (QADD16) and subtraction (QSUB16) functions can then be used with the unpacked values.</p>
<p><strong>Predicate Code Design (cordic_arctan_predicate.c)</strong></p>
<p>This section of the code was designed to minimize any comparison operations that might cause pipeline disruptions due to unexpected branching in the assembly. Bit masking is used to negate operations that are deemed not necessary at runtime, to ensure that the same control path is taken during every execution of the code.</p>
<p><strong>Naive Optimized Code Design (cordic_arctan_naive_optimized.c)</strong></p>
<p>This naive design implementation, after looking at the effectiveness of the above optimizations, is the result combining the Register Code Design and the Unroll Code Design.</p>
<p><strong>Final Optimized Code Design (cordic_arctan_optimized_full_unroll.c)</strong></p>
<p>After looking at the assembly code from the “O3” compiler optimization of the Initial Code Design, several more changes were added to the Naive Optimized Code Design. Firstly, a complete loop unroll was used in place of the single unroll. This means that each of the 15 iterations exist in the C code. Secondly, as there was no need to store the z table values so as to iterate through them dynamically, the same values could be referenced directly as literals. This means that if the register keyword is adhered to within the function, hardly anything should exist in memory at all.</p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image4.png" class="img-fluid"></p>
<p><em>Figure 3. UML of the CORDIC control flow</em></p>
</section>
<section id="c-code-optimization" class="level2">
<h2 class="anchored" data-anchor-id="c-code-optimization">C Code + Optimization</h2>
<p><em>(The C Code and optimization section will explore the various techniques that were applied in this project, expanding on how cycles were saved.)</em></p>
<section id="using-register-key-word" class="level3">
<h3 class="anchored" data-anchor-id="using-register-key-word">Using <code>register</code> Key Word</h3>
<p>By using the register keyword before a variable of 32 bits or less, the compiler can be motivated to use registers as the variables instead of putting them on the stack and fetching and storing them in memory. Store and Load operations are relatively costly operations at 2+ cycles a call. These Load and Store operations could ideally be avoided all together, saving many clock cycles.</p>
</section>
<section id="loop-unrolling" class="level3">
<h3 class="anchored" data-anchor-id="loop-unrolling">Loop Unrolling</h3>
<p>Reasons for loop unrolling include reduced loop control overhead and increased efficiency with pipelining.</p>
<p>The Cortex-M4 CPU utilizes a 3-stage pipelining strategy of Fetch, Decode, and Execute. This means that in optimal code, 3 instructions can be executed in parallel.</p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image5.png" class="img-fluid"></p>
<p><em>Figure 4. From the STM32 manual, we get a brief visual of the Cortex-M4 pipeline with the 3 pipeline operations in an optimised state.</em></p>
<p>By unrolling in certain circumstances, we can remove overhead of the loop AND reduce waiting or NOP usage resulting in less overall clock cycles.</p>
</section>
<section id="cmsis-dsp-intrinsics" class="level3">
<h3 class="anchored" data-anchor-id="cmsis-dsp-intrinsics">CMSIS-DSP Intrinsics</h3>
<p>The hardware for this project allowed for the use of the ARM CMSIS, a standardized layer between the user specific C code and the ARM Cortex-M hardware, that emphasizes portability, readability, performance, and faster development. CMSIS also provides developers access to a whole suite of debugging tools such as the DWT (Data Watchpoint and Trace unit) and SWO (Serial Wire Output), which provided for higher visibility on the project, concerning both debugging and performance evaluations. The DWT-&gt;CYCCNT provided access to the number of cycles which was used to quantify the performance of the code during the application of optimization techniques.</p>
<p>CMSIS-DSP is a library of optimized math functions used for digital signal processing. These functions can allow for SIMD (Single Instruction, Multiple Data) design. This type of arithmetic essentially packs several numbers into a single register, so that operations take place on multiple pieces of data in a single instruction, which increases parallelism by making better use of the pipeline.</p>
<table class="table">
<colgroup>
<col style="width: 33%">
<col style="width: 33%">
<col style="width: 33%">
</colgroup>
<thead>
<tr class="header">
<th>Intrinsic</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>__PKHBT(x, y, 16)</code></td>
<td>Pack Halfword Bottom</td>
<td>Combines two 16-bit values into a single 32-bit register</td>
</tr>
<tr class="even">
<td><code>__SXTB16</code></td>
<td>Sign Extend Byte to Halfword</td>
<td>Takes each byte within the lower and upper halfword of the input and sign-extends it to form two 16-bit values in the output register.</td>
</tr>
<tr class="odd">
<td><code>__QADD</code></td>
<td>Saturating Addition</td>
<td>Performs addition, ensuring that fixed-point calculations would not wrap around on overflow.</td>
</tr>
<tr class="even">
<td><code>__QSUB</code></td>
<td>Saturating Subtraction</td>
<td>Performs subtraction, clamping the result to prevent overflow or underflow instead of allowing wrap-around.</td>
</tr>
</tbody>
</table>
<p><em>Figure 5. A table outlining the DSP intrinsics explored in development.</em></p>
</section>
<section id="branch-elimination-via-predicated-operations" class="level3">
<h3 class="anchored" data-anchor-id="branch-elimination-via-predicated-operations">Branch Elimination via Predicated Operations</h3>
<p>Embedded systems heavily rely on efficient pipelines to fetch, decode, and execute instructions at the same time. Conditional statements in C (IF/ELSE) are translated into assembly, and will either form an IT block or a conditional branch; both using a comparison operation to decide control flow. Unpredictable branch outcomes have the possibility to stall the pipelining as pipeline flushing or NOP operations may occur, which results in cycles being wasted.</p>
<p>Replacing conditional statements with predicate based branchless operations allow for the system to run the same operations without making a comparison, and the need for checking flags. Bit masking will allow these conditions to be converted into a mask, which can select, modify or negate values and run these operations every time, resulting in a more stable control flow.</p>
<p>When evaluating the functions using condition and predicated operations in this project, it was found that the conditional statements resulted in less cycles being used. The version using predicate based operations required a mask to be created and applied to several values, and having to manage intermediate results. These tasks were necessary to be applied during each loop iteration. This extra load on the ALU resulted in a larger cost than the small branch penalty in the unoptimized CORDIC algorithm.</p>
</section>
<section id="replacing-z-table-calculation-with-pre-initialized-values" class="level3">
<h3 class="anchored" data-anchor-id="replacing-z-table-calculation-with-pre-initialized-values">Replacing Z-Table Calculation with Pre-Initialized Values</h3>
<p>The initial code for the project used an implementation of the Z-table calculation algorithm to run before the CORDIC algorithm was used to populate the Z-values. Saving these values and simply assigning them to an array used 0.0683% of the cycles required to calculate them manually each time, from 105301 cycles required to 72.</p>
</section>
</section>
<section id="compiling-c-and-comparing-assembly" class="level2">
<h2 class="anchored" data-anchor-id="compiling-c-and-comparing-assembly">Compiling C and Comparing Assembly</h2>
<p>While exploring options to utilize optimization techniques, it was proven to be useful to enter commands in the terminal which provided outputs for the associated assembly files. The command used was as follows:</p>
<pre><code>arm-none-eabi-gcc -S -mcpu=cortex-m4 -mthumb cordic_arctan_predicate.c</code></pre>
<p>While the last argument of this command changed depending on which function was being tested, it allowed for the exact understanding of the use of the stack, branches, and any additional operations. On top of the DWT, this proved to be an excellent tool in providing metrics regarding the usefulness or futility of the changes being applied to the source code. This examination allowed for the identification of changes in instruction count, memory accesses, and control flow that could confirm whether a given optimization such as loop unrolling, predicate-based branching, or the use of CMSIS intrinsics was going to save or cost cycles before being evaluated in other bench tests.</p>
<p>When paired with performance measurements obtained from the Data Watchpoint and Trace (DWT) unit, this method provided both a quantitative and qualitative assessment of each modification. The DWT offered precise timing data, while the assembly analysis clarified the underlying reasons for observed performance gains or losses. This combination ensured that optimization decisions were supported by both empirical data and a clear understanding of the generated code on the Cortex-M4 architecture.</p>
<p><strong>Final Optimized Code block</strong></p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image6.png" class="img-fluid"> <img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image7.png" class="img-fluid"></p>
<p><em>Figure 6. On the left, we have a condensed version of the Final Optimization Design. On the right, there are the condensed assembly instructions.</em></p>
<p>As can be seen in the assembly code, except for the end when assigning the value to *z, there are no longer any load and store operations. Load and store operations take at least 2 cycles depending on if they are efficiently pipelined or not. Cmp, add, mov, sub, asr, and blt operations are all cheap 1-cycle operations according to the Cortex-M4 instruction set.</p>
</section>
<section id="results" class="level2">
<h2 class="anchored" data-anchor-id="results">Results</h2>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image8.png" class="img-fluid"></p>
<p><em>Figure 7. Output of the testbench showing output value and average cycles per function execution.</em></p>
<p>Let’s explain the above figure that displays our results.</p>
<p>We see that the cost to simply reset the counter and immediately read the value is 3 cycles, so we can assume at least a 3 cycle discrepancy for each measurement. Below, we will inspect each function’s cycle count and output individually.</p>
<p><strong>Library Arctan function</strong></p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image9.png" class="img-fluid"></p>
<p>The math library atan() function, averaged over 100 calls, takes about 632 cycles to complete the computation. The cycle count will be one of our comparators for the success of our optimized functions. The output of this function will be one of our benchmarks for the precision of our refactored functions.</p>
<p><strong>Basic Un-optimized CORDIC Arctan function</strong></p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image10.png" class="img-fluid"></p>
<p>The basic, un-optimized CORDIC arctan function, as laid out in our source documentation, on average, takes about 981 cycles to complete.</p>
<p>Compared to the library atan() function, this is approximately 1.55 times costlier, which is a surprise. However, there could be some optimizations within the library function, or potentially, the simplicity of the values chosen for X and Y, could have led to the library function being quicker. This initial function output deviates from the expected value by about 1%. Considering the precision necessary for the application, and if we assume the calculations are not compounded, this is good.</p>
<p><strong>CMSIS CORDIC Arctan Function</strong></p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image11.png" class="img-fluid"></p>
<p>Using the CMSIS implementation to pack and unpack the 16-bit integers into a 32-bit container as well as using the QADD/SUB16 16-bit arithmetic operations did not appear to improve the cycle count. In fact, compared to the initial CORDIC function, there was about a 67% increase (formula at Appendix A), likely largely in part due to the expensive packing and unpacking that was implemented on each loop iteration. We also saw a decrease in precision, more than likely because of the reduced precision of using 16-bit integers.</p>
<p><strong>Predicate CORDIC Arctan Function</strong></p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image12.png" class="img-fluid"></p>
<p>The predicate function, like the CMSIS function, did not yield the results that we had hoped for with a 60% increase in clock cycle usage. However, it did produce the same value as the initial CORDIC function.</p>
<p><strong>Register CORDIC Arctan Function</strong></p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image13.png" class="img-fluid"></p>
<p>The easiest change that resulted in the largest improvement was seen in the register CORDIC arctan function. There was approximately 59% decrease in clock cycles while maintaining the same precision.</p>
<p>It can be assumed then, by looking at the result of this measurement (without needing to look at the assembly), that the local variables were indeed stored in registers.</p>
<p><strong>Unrolled CORDIC Arctan Function</strong></p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image14.png" class="img-fluid"></p>
<p>Here, we also saw a decrease in clock cycle usage while still outputting the same value. This decrease at ~6% was not as substantial as the register keyword implementation, but a decrease nonetheless.</p>
<p><strong>Naive Optimized CORDIC Arctan Function</strong></p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image15.png" class="img-fluid"></p>
<p>Using the results from above, we combined the optimizations that showed a decrease in clock cycle usage and created our first optimized solution which later on took the addition of “naive” into its title. The output is still the same value which is good, and we saw a ~61% decrease in clock cycle usage due to our choice of optimizations…</p>
<p>But…</p>
<p>After running compiler optimizations on the initial CORDIC Arctan function, we considered if we could do better.</p>
<p><strong>O1, O2, O3, and Ofast Compiler Optimizations on Initial Un-optimized CORDIC function</strong></p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image16.png" class="img-fluid"></p>
<p>They all output the same value, so we can assume that nothing integral to calculation consistency was optimized away. The clock cycle percentage decreases against the initial CORDIC function are as follows:</p>
<ul>
<li>O1 = ~72%</li>
<li>O2 = ~74%</li>
<li>O3 = ~81%</li>
<li>Ofast = ~81%</li>
</ul>
<p>Wanting to avoid any potential optimization that may reduce precision, we decided to look into some of the optimizations that O3 employed. The largest optimization that we saw was one that we already partially implemented, and that was a complete loop unroll. Once the loop was gone, and all 15 iterations were laid out in C code, it became apparent that we could remove the z_table all together, using literals instead. This would allow for almost everything to exist inside the CPU without needing the load and store operations to access memory.</p>
<p><strong>Final Optimized CORDIC Arctan Function</strong></p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image17.png" class="img-fluid"></p>
<p>And with these couple optimizations added to the naive optimization, we were able to get an average just slightly lower than those of O3 and Ofast at about 4 cycles still at about ~81% reduction in clock cycle usage.</p>
<p>Moreover, outside of the actual CORDIC function optimizations, at the beginning of the project, the Z-table calculation was reconfigured from a runtime calculation to a preinitialized look-up table (LUT). The cycle cost of the runtime calculation was 105301 cycles, while creating the look-up table required only 72 cycles. If one were to include those changes in the final percentage change, the initial value of the unoptimized CORDIC with runtime Z-table calculations would be 106282, and the optimized CORDIC using the preinitialized look-up table using 256 cycles, resulting in a ~99.75% reduction in clock cycle usage.</p>
</section>
<section id="improvements" class="level2">
<h2 class="anchored" data-anchor-id="improvements">Improvements</h2>
<p><em>(Further possible developments in implementation and optimization to the project are discussed in the improvements section.)</em></p>
<p><strong>Increased Precision</strong></p>
<p>Our primary focus throughout this project was on reducing the amount of cycles called per function; however, we consistently had an error (compared to the atan() library function) of about 1%. If this error were to be too great for a client, we would have to consider options such as a larger bit-width integer and more values held in the z_table leading to more rotation iterations.</p>
<p><strong>Remove Branches</strong></p>
<p>Although it may be difficult to tell the compiler to use the predicate operations, we may be able to enforce branchless operations by using a bit mask operation with XOR to dynamically replace addition and subtraction operations.</p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image18.png" class="img-fluid"></p>
<p><em>Figure 8. Example of removing branches</em></p>
<p><strong>Use Restrict Keyword with Pointer Variable</strong></p>
<p>Use of the restrict keyword tells the compiler that the pointer is unique and can therefore optimize the code as much as it likes because it is aware of all possible modifications to the pointer and its contents because it has the entire context.</p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image19.png" class="img-fluid"></p>
<p><em>Figure 9. Example of using restrict keyword with the pointer to z_d</em></p>
<p><strong>Eliminate Temporary Variables</strong></p>
<p>Not only do variables take up a register (in our case) that could be used for something else, if using them to store the results from an addition or subtraction, they will incur an extra move operation. Attempting to remove temporary variables in preference of self-assignment could result in more clock cycles saved.</p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image20.png" class="img-fluid"></p>
<p><em>Figure 10. Example of removing a temp variable for self-assignment</em></p>
<p><strong>Use inline keyword</strong></p>
<p>Using the inline keyword within the function declaration tells the compiler to place the function code directly inside the calling code block. This saves on the overhead associated with calling the function.</p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image21.png" class="img-fluid"></p>
<p><em>Figure 11. Example of a function declaration using inline</em></p>
<p><strong>Peripheral Hardware Integration</strong></p>
<p>While the current implementation of the project achieves low-latency trigonometric functions, the algorithm is performing calculations on hardcoded inputs, instead of external, real-time data. The speeds achieved are not likely to be replicated if there were a need to interface with multiple inputs outside of values written in the code itself. Moreover, many real world applications of such CORDIC would utilize more than one data stream, and therefore benefit from true parallelism.</p>
<p>Changes to such applications might require consideration of a different microprocessor. One with compatibility with specific CMSIS functions, such as onboard vector calculation abilities to better utilize design paradigms such as SIMD.</p>
<p>Such applications would require interfacing with SPI/DMA on the hardware, which will also create issues surrounding the timing of gathering inputs and performing calculations. External arithmetic hardware such as a DSP (Digital Signal Processor), FPGA or even an external microcontroller with more FPU capabilities might serve to delegate the repeated algorithms outside of the main system. This would allow for increases in speed, precision, and extra functionality.</p>
<p><strong>Safe Coding Practices</strong></p>
<p>Barr-C is a set of coding best practices specifically designed for embedded systems that emphasize reliability, predictability, and portability. This project implemented several of these techniques to ensure safety such as designing single responsibility functions, marking read-only input values as const (demonstrated in the LUT), implementing the restrict keyword on non-aliasing pointers for better code generation, replacing numeric literals with defined constants for readability and maintainability, using signed saturation functions to prevent overflow/underflow in fixed point, and employing unit tests, quantifying errors.</p>
</section>
<section id="conclusions" class="level2">
<h2 class="anchored" data-anchor-id="conclusions">Conclusions</h2>
<p>This project successfully demonstrated that significant performance gains can be achieved in a CORDIC arctangent implementation through targeted, low-level optimizations while preserving acceptable numerical precision. Starting from a baseline of approximately 982 cycles, we were able to reduce execution time to ~184 cycles through a combination of manual optimizations and compiler-assisted enhancements — an ~81% improvement over the initial unoptimized version. When factoring in the transition from a runtime-generated Z-table to a preinitialized lookup table, the total reduction in cycle count reached nearly 99.75%.</p>
<p>The most impactful optimizations were the elimination of memory accesses through full loop unrolling, replacement of the Z-table with compile-time constants, and ensuring variables remained in registers. These techniques, along with careful consideration of compiler optimization strategies, allowed the final implementation to achieve performance on par with aggressive compiler settings such as O3 and Ofast, without introducing loss of precision beyond the baseline 1% error margin relative to the standard library atan() function.</p>
<p>Despite the fact that several of the optimization techniques that were explored ended up costing the system more cycles and overall reducing efficiency, some of these techniques would dramatically improve a system with real world application. Where SIMD design techniques only increased overhead in our single calculation system, any system with multiple streams of input would definitely benefit from such design changes.</p>
<p>While the primary focus was on speed, several potential avenues for further improvement have been identified. Increasing precision through expanded bit-width and additional rotation iterations, enforcing branchless execution, eliminating unnecessary temporaries, and leveraging keywords such as “restrict” and “inline” could yield additional efficiency. Furthermore, integrating the algorithm into a real-time, peripheral-driven workflow and exploring parallel data handling would extend its applicability to practical embedded systems scenarios.</p>
<p>Overall, this work not only achieved its performance objectives but also provided valuable insights into the trade-offs and opportunities in optimizing mathematical algorithms for microcontrollers. The resulting implementation offers a strong foundation for both higher-precision variants and broader system integration in future development.</p>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<p>[1] J. T. Arbaugh, “Table Look-up CORDIC: Effective Rotations Through Angle Partitioning,” dissertation, 2004</p>
<p>[2] AN5325 - how to use the Cordic to perform mathematical …, https://www.st.com/resource/en/application_note/an5325-how-to-use-the-cordic-to-perform-mathematical-functions-on-stm32-mcus-stmicroelectronics.pdf (accessed Jun.&nbsp;1, 2025).</p>
<p>[3] “STM32F0DISCOVERY,” STMicroelectronics, https://www.st.com/en/evaluation-tools/stm32f0discovery.html (accessed May 31, 2025).</p>
<p>[4] STM32 cortex®-M4 mcus and MPUS Programming manual, https://www.st.com/resource/en/programming_manual/pm0214-stm32-cortexm4-mcus-and-mpus-programming-manual-stmicroelectronics.pdf (accessed Jun.&nbsp;1, 2025).</p>
<p>[5] https://www.st.com/resource/en/reference_manual/dm00031020-stm32f405-415-stm32f407-417-stm32f427-437-and-stm32f429-439-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf</p>
<p>[6] J. E. Volder, “The Birth of Cordic,” <em>The Journal of VLSI Signal Processing</em>, vol.&nbsp;25, no. 2, pp.&nbsp;101–105, 2000. doi:10.1023/a:1008110704586</p>
</section>
<section id="appendices" class="level2">
<h2 class="anchored" data-anchor-id="appendices">Appendices</h2>
<p><strong>Appendix A</strong> The following formula was used to calculate the percentage change:</p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image22.png" class="img-fluid"></p>
<p><strong>Appendix B</strong></p>
<p><img src="https://notes.zakacat.ca/notebooks/images/cordic-optimization/image23.png" class="img-fluid"></p>


</section>


 ]]></description>
  <category>embedded-systems</category>
  <category>arm</category>
  <category>optimization</category>
  <category>dsp</category>
  <guid>https://notes.zakacat.ca/notebooks/CORDIC-Optimization-STM32.html</guid>
  <pubDate>Fri, 01 Aug 2025 00:00:00 GMT</pubDate>
</item>
</channel>
</rss>
