mirror of
https://github.com/youwen5/blog.git
synced 2025-02-20 01:31:10 -08:00
Deploy to GitHub pages
This commit is contained in:
commit
6412a0ca64
15 changed files with 6232 additions and 0 deletions
1
CNAME
Normal file
1
CNAME
Normal file
|
@ -0,0 +1 @@
|
|||
blog.youwen.dev
|
269
a-haskellian-blog.html
Normal file
269
a-haskellian-blog.html
Normal file
|
@ -0,0 +1,269 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>a haskellian blog | The Involution</title>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="a purely functional...blog?" />
|
||||
|
||||
<meta name="author" content="Youwen Wu" />
|
||||
|
||||
<meta name="keywords" content="haskell, blog, functional programming" />
|
||||
|
||||
|
||||
<meta property="og:site_name" content="The Involution" />
|
||||
<meta property="og:title" content="a haskellian blog" />
|
||||
<meta property="og:url" content="https://blog.youwen.dev/a-haskellian-blog.html" />
|
||||
<meta property="og:description" content="a purely functional...blog?" />
|
||||
|
||||
<meta property="og:image" content="https://blog.youwen.dev./images/conditional-finality.png" />
|
||||
|
||||
<meta property="og:type" content="article" />
|
||||
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:image" content="https://blog.youwen.dev./images/conditional-finality.png" />
|
||||
|
||||
<meta property="twitter:site" content="The Involution" />
|
||||
<meta property="twitter:title" content="a haskellian blog" />
|
||||
<meta property="twitter:description" content="a purely functional...blog?" />
|
||||
|
||||
<meta property="twitter:creator" content="@youwen" />
|
||||
|
||||
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="canonical" href="https://blog.youwen.dev/a-haskellian-blog.html" />
|
||||
|
||||
<link
|
||||
rel="alternate"
|
||||
href="./atom.xml"
|
||||
title="The Involution"
|
||||
type="application/atom+xml"
|
||||
/>
|
||||
<link
|
||||
rel="alternate"
|
||||
href="./rss.xml"
|
||||
title="The Involution"
|
||||
type="application/rss+xml"
|
||||
/>
|
||||
<link rel="stylesheet" href="./out/bundle.css" />
|
||||
<link rel="stylesheet" href="./css/code.css" />
|
||||
<script
|
||||
defer
|
||||
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/mml-chtml.js"
|
||||
></script>
|
||||
|
||||
<script>
|
||||
if (
|
||||
localStorage.theme === "dark" ||
|
||||
(!("theme" in localStorage) &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches)
|
||||
) {
|
||||
document.documentElement.classList.add("dark")
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark")
|
||||
}
|
||||
window.onload = () => {
|
||||
var themeButton = document.getElementById("theme-toggle")
|
||||
const theme = localStorage.getItem("theme")
|
||||
if (theme === "light") {
|
||||
themeButton.innerText = "theme: light"
|
||||
} else if (theme === "dark") {
|
||||
themeButton.innerText = "theme: dark"
|
||||
} else {
|
||||
themeButton.innerText = "theme: system"
|
||||
}
|
||||
var fontButton = document.getElementById("font-toggle")
|
||||
const font = localStorage.getItem("font")
|
||||
if (font && font === "serif") {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
document.body.classList.add("font-serif")
|
||||
fontButton.innerText = "serif"
|
||||
}
|
||||
if (font && font === "sans") {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
document.body.classList.add("font-sans")
|
||||
fontButton.innerText = "sans"
|
||||
}
|
||||
if (!font) {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
fontButton.innerText = "serif"
|
||||
}
|
||||
}
|
||||
MathJax = {
|
||||
startup: {
|
||||
ready: function () {
|
||||
MathJax.startup.defaultReady()
|
||||
MathJax.startup.promise.then(function () {
|
||||
MathJax.mathml2svgPromise(document.body)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body
|
||||
class="container max-w-3xl mx-auto px-4 transition-colors duration-[2s]"
|
||||
>
|
||||
<header class="mt-14 md:mt-24 mb-14">
|
||||
<div class="inline-flex items-center w-full">
|
||||
<h1 class="text-4xl md:text-5xl font-serif font-medium">
|
||||
<a
|
||||
href="/"
|
||||
class="dark:hover:text-muted-dark hover:text-muted-light transition-all duration-500 text-nowrap tracking-wide"
|
||||
><em>The Involution.</em></a
|
||||
>
|
||||
</h1>
|
||||
<div
|
||||
class="w-full flex-grow flex-shrink rounded-lg h-1 bg-muted-light dark:bg-muted-dark mx-4"
|
||||
></div>
|
||||
</div>
|
||||
<p class="mt-8 mb-3 px-1 italic font-light">
|
||||
a web-log about computers and math and hacking.
|
||||
</p>
|
||||
<a class="text-sm text-iris-light dark:text-iris-dark hover:text-love-light dark:hover:text-love-dark" href="https://youwen.dev"
|
||||
><em>by </em>Youwen Wu</a
|
||||
>
|
||||
<span class="ml-2 font-serif">|</span>
|
||||
<button
|
||||
id="theme-toggle"
|
||||
class="ml-2 text-sm hover:text-accent-light dark:hover:text-muted-dark"
|
||||
></button>
|
||||
<span class="ml-2 font-serif">|</span>
|
||||
<button
|
||||
id="font-toggle"
|
||||
class="ml-2 text-sm hover:text-accent-light dark:hover:text-muted-dark"
|
||||
></button>
|
||||
</header>
|
||||
<article>
|
||||
<header>
|
||||
<h1 class="text-4xl">
|
||||
<a href="./a-haskellian-blog.html">a haskellian blog</a>
|
||||
</h1>
|
||||
<p
|
||||
class="mb-1 mt-2 italic font-light text-lg text-accent-light dark:text-accent-dark"
|
||||
>
|
||||
a purely functional...blog?
|
||||
</p>
|
||||
<div class="mt-2">2024-05-25</div>
|
||||
<div class="mt-1 text-sm">
|
||||
(last updated: 2024-05-25T12:00:00Z)
|
||||
</div>
|
||||
</header>
|
||||
<main class="post mt-4"><p>Welcome! This is the first post on <em>The Involution</em> and also one that tests all
|
||||
of the features.</p>
|
||||
<!--<img-->
|
||||
<!-- alt="conditional finality"-->
|
||||
<!-- src="./images/conditional-finality.png"-->
|
||||
<!--/>-->
|
||||
<blockquote>
|
||||
<p>A monad is just a monoid in the category of endofunctors, what’s the problem?</p>
|
||||
</blockquote>
|
||||
<h2 id="haskell">haskell?</h2>
|
||||
<p>This entire blog is generated with <a href="https://jaspervdj.be/hakyll/">hakyll</a>. It’s
|
||||
a library for generating static sites for Haskell, a purely functional
|
||||
programming language. It’s a <em>library</em> because it doesn’t come with as many
|
||||
batteries included as tools like Hugo or Astro. You set up most of the site
|
||||
yourself by calling the library from Haskell.</p>
|
||||
<p>Here’s a brief excerpt:</p>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">main ::</span> <span class="dt">IO</span> ()</span>
|
||||
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>main <span class="ot">=</span> hakyllWith config <span class="op">$</span> <span class="kw">do</span></span>
|
||||
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> forM_</span>
|
||||
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> [ <span class="st">"CNAME"</span></span>
|
||||
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> , <span class="st">"favicon.ico"</span></span>
|
||||
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> , <span class="st">"robots.txt"</span></span>
|
||||
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> , <span class="st">"_config.yml"</span></span>
|
||||
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> , <span class="st">"images/*"</span></span>
|
||||
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> , <span class="st">"out/*"</span></span>
|
||||
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> , <span class="st">"fonts/*"</span></span>
|
||||
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> ]</span>
|
||||
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> <span class="op">$</span> \f <span class="ot">-></span> match f <span class="op">$</span> <span class="kw">do</span></span>
|
||||
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> route idRoute</span>
|
||||
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> compile copyFileCompiler</span></code></pre></div>
|
||||
<p>The code highlighting is also generated by hakyll.</p>
|
||||
<hr />
|
||||
<h2 id="why">why?</h2>
|
||||
<p>Haskell is a purely functional language with no mutable state. Its syntax
|
||||
actually makes it pretty elegant for declaring routes and “rendering” pipelines.</p>
|
||||
<ol>
|
||||
<li>Haskell is cool.</li>
|
||||
<li>It comes with enough features that I don’t feel like I have to build
|
||||
everything from scratch.</li>
|
||||
<li>It comes with Pandoc, a Haskell library for converting between markdown
|
||||
formats. It’s probably more powerful than anything you could do in <code>nodejs</code>.
|
||||
It renders all of the markdown to HTML as well as the math.
|
||||
<ol>
|
||||
<li>It supports KaTeX as well as MathML. I’m a little disappointed with the
|
||||
KaTeX though. It doesn’t directly render it, but simply injects the KaTeX
|
||||
files and renders it client-side.</li>
|
||||
</ol></li>
|
||||
</ol>
|
||||
<h3 id="speaking-of-math">speaking of math</h3>
|
||||
<p>We can have math inline, like so:
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mo>∫</mo><mrow><mi>−</mi><mi>∞</mi></mrow><mi>∞</mi></msubsup><mspace width="0.167em"></mspace><msup><mi>e</mi><mrow><mi>−</mi><msup><mi>x</mi><mn>2</mn></msup></mrow></msup><mspace width="0.167em"></mspace><mi>d</mi><mi>x</mi><mo>=</mo><msqrt><mi>π</mi></msqrt></mrow><annotation encoding="application/x-tex">\int_{-\infty}^\infty \, e^{-x^2}\,dx = \sqrt{\pi}</annotation></semantics></math>. This site ships semantic
|
||||
MathML math with its HTML, and the MathJax script to the client.</p>
|
||||
<p>It’d be nice if MathML could just be used and supported across all browsers, but
|
||||
unfortunately we still aren’t quite there yet. Firefox is the only one where
|
||||
everything looks 80% of the way to LaTeX. On Safari and Chrome, even simple
|
||||
equations like <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msqrt><mi>π</mi></msqrt><annotation encoding="application/x-tex">\sqrt{\pi}</annotation></semantics></math> render improperly.</p>
|
||||
<p>Pros of MathML:</p>
|
||||
<ul>
|
||||
<li>A little more accessible</li>
|
||||
<li>Can be rendered without additional stylesheets. I just installed the Latin
|
||||
Modern font, but this isn’t even really necessary</li>
|
||||
<li>Built-in to most browsers (#UseThePlatform)</li>
|
||||
</ul>
|
||||
<p>Cons:</p>
|
||||
<ul>
|
||||
<li>Isn’t fully standardized. Might look different on different browsers</li>
|
||||
<li>Rendering quality isn’t as good as KaTeX</li>
|
||||
</ul>
|
||||
<p>This site has MathJax render all of the math so it looks nice and standardized
|
||||
across browsers, but the math still displays regardless (like say if MathJax
|
||||
couldn’t load due to slow network) because of MathML. Best of both worlds.</p>
|
||||
<p>Let’s try it now. Here’s a simple theorem:</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>a</mi><mi>n</mi></msup><mo>+</mo><msup><mi>b</mi><mi>n</mi></msup><mo>≠</mo><msup><mi>c</mi><mi>n</mi></msup><mspace width="0.167em"></mspace><mo>∀</mo><mspace width="0.167em"></mspace><mrow><mo stretchy="true" form="prefix">{</mo><mi>a</mi><mo>,</mo><mspace width="0.167em"></mspace><mi>b</mi><mo>,</mo><mspace width="0.167em"></mspace><mi>c</mi><mo stretchy="true" form="postfix">}</mo></mrow><mo>∈</mo><mi>ℤ</mi><mo>∧</mo><mi>n</mi><mo>≥</mo><mn>3</mn></mrow><annotation encoding="application/x-tex">
|
||||
a^n + b^n \ne c^n \, \forall\,\left\{ a,\,b,\,c \right\} \in \mathbb{Z} \land n \ge 3
|
||||
</annotation></semantics></math></p>
|
||||
<p>The proof is trivial and will be left as an exercise to the reader.</p>
|
||||
<h2 id="seems-a-little-overengineered">seems a little overengineered</h2>
|
||||
<p>Probably is. Not as much as the old one, though.</p></main>
|
||||
</article>
|
||||
|
||||
<footer class="mt-14 md:mt-24 pb-12 font-light">
|
||||
<hr
|
||||
class="border-0 dark:bg-muted-dark bg-muted-light rounded-xl h-0.5 mb-4"
|
||||
/>
|
||||
<p class="text-sm leading-relaxed">
|
||||
© 2024 Youwen Wu. Generated by
|
||||
<a
|
||||
href="https://jaspervdj.be/hakyll/"
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
>Hakyll.</a
|
||||
>
|
||||
View the source
|
||||
<a
|
||||
href="https://github.com/couscousdude/blog"
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
>on GitHub.</a
|
||||
>
|
||||
</p>
|
||||
<p class="text-sm leading-relaxed mt-2">
|
||||
Content freely available under
|
||||
<a
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en"
|
||||
><span class="smallcaps">CC BY-NC-SA</span> 4.0</a
|
||||
>
|
||||
unless otherwise noted.
|
||||
</p>
|
||||
</footer>
|
||||
<script defer src="./out/bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
604
an-assortment-of-preliminaries-on-linear-algebra.html
Normal file
604
an-assortment-of-preliminaries-on-linear-algebra.html
Normal file
|
@ -0,0 +1,604 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>An assortment of preliminaries on linear algebra | The Involution</title>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="and also a test for pandoc" />
|
||||
|
||||
<meta name="author" content="Youwen Wu" />
|
||||
|
||||
<meta name="keywords" content="linear algebra, algebra, math" />
|
||||
|
||||
|
||||
<meta property="og:site_name" content="The Involution" />
|
||||
<meta property="og:title" content="An assortment of preliminaries on linear algebra" />
|
||||
<meta property="og:url" content="https://blog.youwen.dev/an-assortment-of-preliminaries-on-linear-algebra.html" />
|
||||
<meta property="og:description" content="and also a test for pandoc" />
|
||||
|
||||
<meta property="og:image" content="https://blog.youwen.devhttps://wallpapercave.com/wp/wp12329537.png" />
|
||||
|
||||
<meta property="og:type" content="article" />
|
||||
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:image" content="https://blog.youwen.devhttps://wallpapercave.com/wp/wp12329537.png" />
|
||||
|
||||
<meta property="twitter:site" content="The Involution" />
|
||||
<meta property="twitter:title" content="An assortment of preliminaries on linear algebra" />
|
||||
<meta property="twitter:description" content="and also a test for pandoc" />
|
||||
|
||||
<meta property="twitter:creator" content="@youwen" />
|
||||
|
||||
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="canonical" href="https://blog.youwen.dev/an-assortment-of-preliminaries-on-linear-algebra.html" />
|
||||
|
||||
<link
|
||||
rel="alternate"
|
||||
href="./atom.xml"
|
||||
title="The Involution"
|
||||
type="application/atom+xml"
|
||||
/>
|
||||
<link
|
||||
rel="alternate"
|
||||
href="./rss.xml"
|
||||
title="The Involution"
|
||||
type="application/rss+xml"
|
||||
/>
|
||||
<link rel="stylesheet" href="./out/bundle.css" />
|
||||
<link rel="stylesheet" href="./css/code.css" />
|
||||
<script
|
||||
defer
|
||||
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/mml-chtml.js"
|
||||
></script>
|
||||
|
||||
<script>
|
||||
if (
|
||||
localStorage.theme === "dark" ||
|
||||
(!("theme" in localStorage) &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches)
|
||||
) {
|
||||
document.documentElement.classList.add("dark")
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark")
|
||||
}
|
||||
window.onload = () => {
|
||||
var themeButton = document.getElementById("theme-toggle")
|
||||
const theme = localStorage.getItem("theme")
|
||||
if (theme === "light") {
|
||||
themeButton.innerText = "theme: light"
|
||||
} else if (theme === "dark") {
|
||||
themeButton.innerText = "theme: dark"
|
||||
} else {
|
||||
themeButton.innerText = "theme: system"
|
||||
}
|
||||
var fontButton = document.getElementById("font-toggle")
|
||||
const font = localStorage.getItem("font")
|
||||
if (font && font === "serif") {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
document.body.classList.add("font-serif")
|
||||
fontButton.innerText = "serif"
|
||||
}
|
||||
if (font && font === "sans") {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
document.body.classList.add("font-sans")
|
||||
fontButton.innerText = "sans"
|
||||
}
|
||||
if (!font) {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
fontButton.innerText = "serif"
|
||||
}
|
||||
}
|
||||
MathJax = {
|
||||
startup: {
|
||||
ready: function () {
|
||||
MathJax.startup.defaultReady()
|
||||
MathJax.startup.promise.then(function () {
|
||||
MathJax.mathml2svgPromise(document.body)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body
|
||||
class="container max-w-3xl mx-auto px-4 transition-colors duration-[2s]"
|
||||
>
|
||||
<header class="mt-14 md:mt-24 mb-14">
|
||||
<div class="inline-flex items-center w-full">
|
||||
<h1 class="text-4xl md:text-5xl font-serif font-medium">
|
||||
<a
|
||||
href="/"
|
||||
class="dark:hover:text-muted-dark hover:text-muted-light transition-all duration-500 text-nowrap tracking-wide"
|
||||
><em>The Involution.</em></a
|
||||
>
|
||||
</h1>
|
||||
<div
|
||||
class="w-full flex-grow flex-shrink rounded-lg h-1 bg-muted-light dark:bg-muted-dark mx-4"
|
||||
></div>
|
||||
</div>
|
||||
<p class="mt-8 mb-3 px-1 italic font-light">
|
||||
a web-log about computers and math and hacking.
|
||||
</p>
|
||||
<a class="text-sm text-iris-light dark:text-iris-dark hover:text-love-light dark:hover:text-love-dark" href="https://youwen.dev"
|
||||
><em>by </em>Youwen Wu</a
|
||||
>
|
||||
<span class="ml-2 font-serif">|</span>
|
||||
<button
|
||||
id="theme-toggle"
|
||||
class="ml-2 text-sm hover:text-accent-light dark:hover:text-muted-dark"
|
||||
></button>
|
||||
<span class="ml-2 font-serif">|</span>
|
||||
<button
|
||||
id="font-toggle"
|
||||
class="ml-2 text-sm hover:text-accent-light dark:hover:text-muted-dark"
|
||||
></button>
|
||||
</header>
|
||||
<article>
|
||||
<header>
|
||||
<h1 class="text-4xl">
|
||||
<a href="./an-assortment-of-preliminaries-on-linear-algebra.html">An assortment of preliminaries on linear algebra</a>
|
||||
</h1>
|
||||
<p
|
||||
class="mb-1 mt-2 italic font-light text-lg text-accent-light dark:text-accent-dark"
|
||||
>
|
||||
and also a test for pandoc
|
||||
</p>
|
||||
<div class="mt-2">2025-02-15</div>
|
||||
<div class="mt-1 text-sm">
|
||||
|
||||
</div>
|
||||
</header>
|
||||
<main class="post mt-4"><p>This entire document was written entirely in <a href="https://typst.app/">Typst</a> and
|
||||
directly translated to this file by Pandoc. It serves as a proof of concept of
|
||||
a way to do static site generation from Typst files instead of Markdown.</p>
|
||||
<hr />
|
||||
<p>I figured I should write this stuff down before I forgot it.</p>
|
||||
<h1 id="basic-notions">Basic Notions</h1>
|
||||
<h2 id="vector-spaces">Vector spaces</h2>
|
||||
<p>Before we can understand vectors, we need to first discuss <em>vector
|
||||
spaces</em>. Thus far, you have likely encountered vectors primarily in
|
||||
physics classes, generally in the two-dimensional plane. You may
|
||||
conceptualize them as arrows in space. For vectors of size <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>></mo><mn>3</mn></mrow><annotation encoding="application/x-tex">> 3</annotation></semantics></math>, a hand
|
||||
waving argument is made that they are essentially just arrows in higher
|
||||
dimensional spaces.</p>
|
||||
<p>It is helpful to take a step back from this primitive geometric
|
||||
understanding of the vector. Let us build up a rigorous idea of vectors
|
||||
from first principles.</p>
|
||||
<h3 id="vector-axioms">Vector axioms</h3>
|
||||
<p>The so-called <em>axioms</em> of a <em>vector space</em> (which we’ll call the vector
|
||||
space <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>V</mi><annotation encoding="application/x-tex">V</annotation></semantics></math>) are as follows:</p>
|
||||
<ol>
|
||||
<li><p>Commutativity: <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi><mo>+</mo><mi>v</mi><mo>=</mo><mi>v</mi><mo>+</mo><mi>u</mi><mo>,</mo><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> </mtext><mspace width="0.333em"></mspace></mrow><mo>∀</mo><mi>u</mi><mo>,</mo><mi>v</mi><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">u + v = v + u,\text{ }\forall u,v \in V</annotation></semantics></math></p></li>
|
||||
<li><p>Associativity:
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mi>u</mi><mo>+</mo><mi>v</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>+</mo><mi>w</mi><mo>=</mo><mi>u</mi><mo>+</mo><mrow><mo stretchy="true" form="prefix">(</mo><mi>v</mi><mo>+</mo><mi>w</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>,</mo><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> </mtext><mspace width="0.333em"></mspace></mrow><mo>∀</mo><mi>u</mi><mo>,</mo><mi>v</mi><mo>,</mo><mi>w</mi><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">(u + v) + w = u + (v + w),\text{ }\forall u,v,w \in V</annotation></semantics></math></p></li>
|
||||
<li><p>Zero vector: <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mo>∃</mo><annotation encoding="application/x-tex">\exists</annotation></semantics></math> a special vector, denoted <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mn>0</mn><annotation encoding="application/x-tex">0</annotation></semantics></math>, such that
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>+</mo><mn>0</mn><mo>=</mo><mi>v</mi><mo>,</mo><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> </mtext><mspace width="0.333em"></mspace></mrow><mo>∀</mo><mi>v</mi><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">v + 0 = v,\text{ }\forall v \in V</annotation></semantics></math></p></li>
|
||||
<li><p>Additive inverse:
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>∀</mo><mi>v</mi><mo>∈</mo><mi>V</mi><mo>,</mo><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> </mtext><mspace width="0.333em"></mspace></mrow><mo>∃</mo><mi>w</mi><mo>∈</mo><mi>V</mi><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> such that </mtext><mspace width="0.333em"></mspace></mrow><mi>v</mi><mo>+</mo><mi>w</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\forall v \in V,\text{ }\exists w \in V\text{ such that }v + w = 0</annotation></semantics></math>.
|
||||
Such an additive inverse is generally denoted <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>−</mi><mi>v</mi></mrow><annotation encoding="application/x-tex">- v</annotation></semantics></math></p></li>
|
||||
<li><p>Multiplicative identity: <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mi>v</mi><mo>=</mo><mi>v</mi><mo>,</mo><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> </mtext><mspace width="0.333em"></mspace></mrow><mo>∀</mo><mi>v</mi><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">1v = v,\text{ }\forall v \in V</annotation></semantics></math></p></li>
|
||||
<li><p>Multiplicative associativity:
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mi>α</mi><mi>β</mi><mo stretchy="true" form="postfix">)</mo></mrow><mi>v</mi><mo>=</mo><mi>α</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>β</mi><mi>v</mi><mo stretchy="true" form="postfix">)</mo></mrow><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> </mtext><mspace width="0.333em"></mspace></mrow><mo>∀</mo><mi>v</mi><mo>∈</mo><mi>V</mi><mo>,</mo><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> scalars </mtext><mspace width="0.333em"></mspace></mrow><mi>α</mi><mo>,</mo><mi>β</mi></mrow><annotation encoding="application/x-tex">(\alpha\beta)v = \alpha(\beta v)\text{ }\forall v \in V,\text{ scalars }\alpha,\beta</annotation></semantics></math></p></li>
|
||||
<li><p>Distributive property for vectors:
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>u</mi><mo>+</mo><mi>v</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mi>α</mi><mi>u</mi><mo>+</mo><mi>α</mi><mi>v</mi><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> </mtext><mspace width="0.333em"></mspace></mrow><mo>∀</mo><mi>u</mi><mo>,</mo><mi>v</mi><mo>∈</mo><mi>V</mi><mo>,</mo><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> scalars </mtext><mspace width="0.333em"></mspace></mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha(u + v) = \alpha u + \alpha v\text{ }\forall u,v \in V,\text{ scalars }\alpha</annotation></semantics></math></p></li>
|
||||
<li><p>Distributive property for scalars:
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mi>α</mi><mo>+</mo><mi>β</mi><mo stretchy="true" form="postfix">)</mo></mrow><mi>v</mi><mo>=</mo><mi>α</mi><mi>v</mi><mo>+</mo><mi>β</mi><mi>v</mi><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> </mtext><mspace width="0.333em"></mspace></mrow><mo>∀</mo><mi>v</mi><mo>∈</mo><mi>V</mi><mo>,</mo><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> scalars </mtext><mspace width="0.333em"></mspace></mrow><mi>α</mi><mo>,</mo><mi>β</mi></mrow><annotation encoding="application/x-tex">(\alpha + \beta)v = \alpha v + \beta v\text{ }\forall v \in V,\text{ scalars }\alpha,\beta</annotation></semantics></math></p></li>
|
||||
</ol>
|
||||
<p>It is easy to show that the zero vector <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mn>0</mn><annotation encoding="application/x-tex">0</annotation></semantics></math> and the additive inverse
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>−</mi><mi>v</mi></mrow><annotation encoding="application/x-tex">- v</annotation></semantics></math> are <em>unique</em>. We leave the proof of this fact as an exercise.</p>
|
||||
<p>These may seem difficult to memorize, but they are essentially the same
|
||||
familiar algebraic properties of numbers you know from high school. The
|
||||
important thing to remember is which operations are valid for what
|
||||
objects. For example, you cannot add a vector and scalar, as it does not
|
||||
make sense.</p>
|
||||
<p><em>Remark</em>. For those of you versed in computer science, you may recognize
|
||||
this as essentially saying that you must ensure your operations are
|
||||
<em>type-safe</em>. Adding a vector and scalar is not just “wrong” in the same
|
||||
sense that <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>+</mo><mn>1</mn><mo>=</mo><mn>3</mn></mrow><annotation encoding="application/x-tex">1 + 1 = 3</annotation></semantics></math> is wrong, it is an <em>invalid question</em> entirely
|
||||
because vectors and scalars and different types of mathematical objects.
|
||||
See [@chen2024digression] for more.</p>
|
||||
<h3 id="vectors-big-and-small">Vectors big and small</h3>
|
||||
<p>In order to begin your descent into what mathematicians colloquially
|
||||
recognize as <em>abstract vapid nonsense</em>, let’s discuss which fields
|
||||
constitute a vector space. We have the familiar field of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>ℝ</mi><annotation encoding="application/x-tex">\mathbb{R}</annotation></semantics></math>
|
||||
where all scalars are real numbers, with corresponding vector spaces
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{n}</annotation></semantics></math>, where <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>n</mi><annotation encoding="application/x-tex">n</annotation></semantics></math> is the length of the vector. We generally
|
||||
discuss 2D or 3D vectors, corresponding to vectors of length 2 or 3; in
|
||||
our case, <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mn>2</mn></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{2}</annotation></semantics></math> and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mn>3</mn></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{3}</annotation></semantics></math>.</p>
|
||||
<p>However, vectors in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{n}</annotation></semantics></math> can really be of any length.
|
||||
Vectors can be viewed as arbitrary length lists of numbers (for the
|
||||
computer science folk: think C++ <code>std::vector</code>).</p>
|
||||
<p><em>Example</em>. <math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>2</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>3</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>4</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>5</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>6</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>7</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>8</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>9</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>∈</mo><msup><mi>ℝ</mi><mn>9</mn></msup></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
1 \\
|
||||
2 \\
|
||||
3 \\
|
||||
4 \\
|
||||
5 \\
|
||||
6 \\
|
||||
7 \\
|
||||
8 \\
|
||||
9
|
||||
\end{pmatrix} \in {\mathbb{R}}^{9}</annotation></semantics></math></p>
|
||||
<p>Keep in mind that vectors need not be in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{n}</annotation></semantics></math> at all.
|
||||
Recall that a vector space need only satisfy the aforementioned <em>axioms
|
||||
of a vector space</em>.</p>
|
||||
<p><em>Example</em>. The vector space <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℂ</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{C}}^{n}</annotation></semantics></math> is similar to
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{n}</annotation></semantics></math>, except it includes complex numbers. All complex
|
||||
vector spaces are real vector spaces (as you can simply restrict them to
|
||||
only use the real numbers), but not the other way around.</p>
|
||||
<p>From now on, let us refer to vector spaces <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{n}</annotation></semantics></math> and
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℂ</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{C}}^{n}</annotation></semantics></math> as <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>𝔽</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{F}}^{n}</annotation></semantics></math>.</p>
|
||||
<p>In general, we can have a vector space where the scalars are in an
|
||||
arbitrary field, as long as the axioms are satisfied.</p>
|
||||
<p><em>Example</em>. The vector space of all polynomials of at most degree 3, or
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℙ</mi><mn>3</mn></msup><annotation encoding="application/x-tex">{\mathbb{P}}^{3}</annotation></semantics></math>. It is not yet clear what this vector may look like.
|
||||
We shall return to this example once we discuss <em>basis</em>.</p>
|
||||
<h2 id="vector-addition-multiplication">Vector addition. Multiplication</h2>
|
||||
<p>Vector addition, represented by <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>+</mi><annotation encoding="application/x-tex">+</annotation></semantics></math> can be done entrywise.</p>
|
||||
<p><em>Example.</em></p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>2</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>3</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>+</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>4</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>5</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>6</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn><mo>+</mo><mn>4</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>2</mn><mo>+</mo><mn>5</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>3</mn><mo>+</mo><mn>6</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>5</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>7</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>9</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
1 \\
|
||||
2 \\
|
||||
3
|
||||
\end{pmatrix} + \begin{pmatrix}
|
||||
4 \\
|
||||
5 \\
|
||||
6
|
||||
\end{pmatrix} = \begin{pmatrix}
|
||||
1 + 4 \\
|
||||
2 + 5 \\
|
||||
3 + 6
|
||||
\end{pmatrix} = \begin{pmatrix}
|
||||
5 \\
|
||||
7 \\
|
||||
9
|
||||
\end{pmatrix}</annotation></semantics></math> <math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>2</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>3</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>⋅</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>4</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>5</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>6</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn><mo>⋅</mo><mn>4</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>2</mn><mo>⋅</mo><mn>5</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>3</mn><mo>⋅</mo><mn>6</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>4</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>10</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>18</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
1 \\
|
||||
2 \\
|
||||
3
|
||||
\end{pmatrix} \cdot \begin{pmatrix}
|
||||
4 \\
|
||||
5 \\
|
||||
6
|
||||
\end{pmatrix} = \begin{pmatrix}
|
||||
1 \cdot 4 \\
|
||||
2 \cdot 5 \\
|
||||
3 \cdot 6
|
||||
\end{pmatrix} = \begin{pmatrix}
|
||||
4 \\
|
||||
10 \\
|
||||
18
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<p>This is simple enough to understand. Again, the difficulty is simply
|
||||
ensuring that you always perform operations with the correct <em>types</em>.
|
||||
For example, once we introduce matrices, it doesn’t make sense to
|
||||
multiply or add vectors and matrices in this fashion.</p>
|
||||
<h2 id="vector-scalar-multiplication">Vector-scalar multiplication</h2>
|
||||
<p>Multiplying a vector by a scalar simply results in each entry of the
|
||||
vector being multiplied by the scalar.</p>
|
||||
<p><em>Example</em>.</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mi>a</mi></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mi>b</mi></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mi>c</mi></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mi>β</mi><mo>⋅</mo><mi>a</mi></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mi>β</mi><mo>⋅</mo><mi>b</mi></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mi>β</mi><mo>⋅</mo><mi>c</mi></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">\beta\begin{pmatrix}
|
||||
a \\
|
||||
b \\
|
||||
c
|
||||
\end{pmatrix} = \begin{pmatrix}
|
||||
\beta \cdot a \\
|
||||
\beta \cdot b \\
|
||||
\beta \cdot c
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<h2 id="linear-combinations">Linear combinations</h2>
|
||||
<p>Given vector spaces <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>V</mi><annotation encoding="application/x-tex">V</annotation></semantics></math> and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>W</mi><annotation encoding="application/x-tex">W</annotation></semantics></math> and vectors <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">v \in V</annotation></semantics></math> and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>w</mi><mo>∈</mo><mi>W</mi></mrow><annotation encoding="application/x-tex">w \in W</annotation></semantics></math>,
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>+</mo><mi>w</mi></mrow><annotation encoding="application/x-tex">v + w</annotation></semantics></math> is the <em>linear combination</em> of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>v</mi><annotation encoding="application/x-tex">v</annotation></semantics></math> and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>w</mi><annotation encoding="application/x-tex">w</annotation></semantics></math>.</p>
|
||||
<h3 id="spanning-systems">Spanning systems</h3>
|
||||
<p>We say that a set of vectors <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mn>1</mn></msub><mo>,</mo><msub><mi>v</mi><mn>2</mn></msub><mo>,</mo><mi>…</mi><mo>,</mo><msub><mi>v</mi><mi>n</mi></msub><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">v_{1},v_{2},\ldots,v_{n} \in V</annotation></semantics></math> <em>span</em> <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>V</mi><annotation encoding="application/x-tex">V</annotation></semantics></math>
|
||||
if the linear combination of the vectors can represent any arbitrary
|
||||
vector <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">v \in V</annotation></semantics></math>.</p>
|
||||
<p>Precisely, given scalars <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>1</mn></msub><mo>,</mo><msub><mi>α</mi><mn>2</mn></msub><mo>,</mo><mi>…</mi><mo>,</mo><msub><mi>α</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">\alpha_{1},\alpha_{2},\ldots,\alpha_{n}</annotation></semantics></math>,</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>1</mn></msub><msub><mi>v</mi><mn>1</mn></msub><mo>+</mo><msub><mi>α</mi><mn>2</mn></msub><msub><mi>v</mi><mn>2</mn></msub><mo>+</mo><mi>…</mi><mo>+</mo><msub><mi>α</mi><mi>n</mi></msub><msub><mi>v</mi><mi>n</mi></msub><mo>=</mo><mi>v</mi><mo>,</mo><mo>∀</mo><mi>v</mi><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">\alpha_{1}v_{1} + \alpha_{2}v_{2} + \ldots + \alpha_{n}v_{n} = v,\forall v \in V</annotation></semantics></math></p>
|
||||
<p>Note that any scalar <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msub><mi>α</mi><mi>k</mi></msub><annotation encoding="application/x-tex">\alpha_{k}</annotation></semantics></math> could be 0. Therefore, it is possible
|
||||
for a subset of a spanning system to also be a spanning system. The
|
||||
proof of this fact is left as an exercise.</p>
|
||||
<h3 id="intuition-for-linear-independence-and-dependence">Intuition for linear independence and dependence</h3>
|
||||
<p>We say that <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>v</mi><annotation encoding="application/x-tex">v</annotation></semantics></math> and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>w</mi><annotation encoding="application/x-tex">w</annotation></semantics></math> are linearly independent if <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>v</mi><annotation encoding="application/x-tex">v</annotation></semantics></math> cannot be
|
||||
represented by the scaling of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>w</mi><annotation encoding="application/x-tex">w</annotation></semantics></math>, and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>w</mi><annotation encoding="application/x-tex">w</annotation></semantics></math> cannot be represented by the
|
||||
scaling of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>v</mi><annotation encoding="application/x-tex">v</annotation></semantics></math>. Otherwise, they are <em>linearly dependent</em>.</p>
|
||||
<p>You may intuitively visualize linear dependence in the 2D plane as two
|
||||
vectors both pointing in the same direction. Clearly, scaling one vector
|
||||
will allow us to reach the other vector. Linear independence is
|
||||
therefore two vectors pointing in different directions.</p>
|
||||
<p>Of course, this definition applies to vectors in any <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>𝔽</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{F}}^{n}</annotation></semantics></math>.</p>
|
||||
<h3 id="formal-definition-of-linear-dependence-and-independence">Formal definition of linear dependence and independence</h3>
|
||||
<p>Let us formally define linear independence for arbitrary vectors in
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>𝔽</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{F}}^{n}</annotation></semantics></math>. Given a set of vectors</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mn>1</mn></msub><mo>,</mo><msub><mi>v</mi><mn>2</mn></msub><mo>,</mo><mi>…</mi><mo>,</mo><msub><mi>v</mi><mi>n</mi></msub><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">v_{1},v_{2},\ldots,v_{n} \in V</annotation></semantics></math></p>
|
||||
<p>we say they are linearly independent iff. the equation</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>1</mn></msub><msub><mi>v</mi><mn>1</mn></msub><mo>+</mo><msub><mi>α</mi><mn>2</mn></msub><msub><mi>v</mi><mn>2</mn></msub><mo>+</mo><mi>…</mi><mo>+</mo><msub><mi>α</mi><mi>n</mi></msub><msub><mi>v</mi><mi>n</mi></msub><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\alpha_{1}v_{1} + \alpha_{2}v_{2} + \ldots + \alpha_{n}v_{n} = 0</annotation></semantics></math></p>
|
||||
<p>has only a unique set of solutions
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>1</mn></msub><mo>,</mo><msub><mi>α</mi><mn>2</mn></msub><mo>,</mo><mi>…</mi><mo>,</mo><msub><mi>α</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">\alpha_{1},\alpha_{2},\ldots,\alpha_{n}</annotation></semantics></math> such that all <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msub><mi>α</mi><mi>n</mi></msub><annotation encoding="application/x-tex">\alpha_{n}</annotation></semantics></math> are
|
||||
zero.</p>
|
||||
<p>Equivalently,</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">|</mo><msub><mi>α</mi><mn>1</mn></msub><mo stretchy="true" form="postfix">|</mo></mrow><mo>+</mo><mrow><mo stretchy="true" form="prefix">|</mo><msub><mi>α</mi><mn>2</mn></msub><mo stretchy="true" form="postfix">|</mo></mrow><mo>+</mo><mi>…</mi><mo>+</mo><mrow><mo stretchy="true" form="prefix">|</mo><msub><mi>α</mi><mi>n</mi></msub><mo stretchy="true" form="postfix">|</mo></mrow><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\left| \alpha_{1} \right| + \left| \alpha_{2} \right| + \ldots + \left| \alpha_{n} \right| = 0</annotation></semantics></math></p>
|
||||
<p>More precisely,</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>k</mi></munderover><mrow><mo stretchy="true" form="prefix">|</mo><msub><mi>α</mi><mi>i</mi></msub><mo stretchy="true" form="postfix">|</mo></mrow><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\sum_{i = 1}^{k}\left| \alpha_{i} \right| = 0</annotation></semantics></math></p>
|
||||
<p>Therefore, a set of vectors <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mn>1</mn></msub><mo>,</mo><msub><mi>v</mi><mn>2</mn></msub><mo>,</mo><mi>…</mi><mo>,</mo><msub><mi>v</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">v_{1},v_{2},\ldots,v_{m}</annotation></semantics></math> is linearly
|
||||
dependent if the opposite is true, that is there exists solution
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>1</mn></msub><mo>,</mo><msub><mi>α</mi><mn>2</mn></msub><mo>,</mo><mi>…</mi><mo>,</mo><msub><mi>α</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">\alpha_{1},\alpha_{2},\ldots,\alpha_{m}</annotation></semantics></math> to the equation</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>1</mn></msub><msub><mi>v</mi><mn>1</mn></msub><mo>+</mo><msub><mi>α</mi><mn>2</mn></msub><msub><mi>v</mi><mn>2</mn></msub><mo>+</mo><mi>…</mi><mo>+</mo><msub><mi>α</mi><mi>m</mi></msub><msub><mi>v</mi><mi>m</mi></msub><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\alpha_{1}v_{1} + \alpha_{2}v_{2} + \ldots + \alpha_{m}v_{m} = 0</annotation></semantics></math></p>
|
||||
<p>such that</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>k</mi></munderover><mrow><mo stretchy="true" form="prefix">|</mo><msub><mi>α</mi><mi>i</mi></msub><mo stretchy="true" form="postfix">|</mo></mrow><mo>≠</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\sum_{i = 1}^{k}\left| \alpha_{i} \right| \neq 0</annotation></semantics></math></p>
|
||||
<h3 id="basis">Basis</h3>
|
||||
<p>We say a system of vectors <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>v</mi><mn>1</mn></msub><mo>,</mo><msub><mi>v</mi><mn>2</mn></msub><mo>,</mo><mi>…</mi><mo>,</mo><msub><mi>v</mi><mi>n</mi></msub><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">v_{1},v_{2},\ldots,v_{n} \in V</annotation></semantics></math> is a <em>basis</em>
|
||||
in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>V</mi><annotation encoding="application/x-tex">V</annotation></semantics></math> if the system is both linearly independent and spanning. That is,
|
||||
the system must be able to represent any vector in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>V</mi><annotation encoding="application/x-tex">V</annotation></semantics></math> as well as
|
||||
satisfy our requirements for linear independence.</p>
|
||||
<p>Equivalently, we may say that a system of vectors in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>V</mi><annotation encoding="application/x-tex">V</annotation></semantics></math> is a basis in
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>V</mi><annotation encoding="application/x-tex">V</annotation></semantics></math> if any vector <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">v \in V</annotation></semantics></math> admits a <em>unique representation</em> as a linear
|
||||
combination of vectors in the system. This is equivalent to our previous
|
||||
statement, that the system must be spanning and linearly independent.</p>
|
||||
<h3 id="standard-basis">Standard basis</h3>
|
||||
<p>We may define a <em>standard basis</em> for a vector space. By convention, the
|
||||
standard basis in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mn>2</mn></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{2}</annotation></semantics></math> is</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
1 \\
|
||||
0
|
||||
\end{pmatrix}\begin{pmatrix}
|
||||
0 \\
|
||||
1
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<p>Verify that the above is in fact a basis (that is, linearly independent
|
||||
and generating).</p>
|
||||
<p>Recalling the definition of the basis, we can represent any vector in
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mn>2</mn></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{2}</annotation></semantics></math> as the linear combination of the standard basis.</p>
|
||||
<p>Therefore, for any arbitrary vector <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>∈</mo><msup><mi>ℝ</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">v \in {\mathbb{R}}^{2}</annotation></semantics></math>, we can
|
||||
represent it as</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>=</mo><msub><mi>α</mi><mn>1</mn></msub><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>+</mo><msub><mi>α</mi><mn>2</mn></msub><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">v = \alpha_{1}\begin{pmatrix}
|
||||
1 \\
|
||||
0
|
||||
\end{pmatrix} + \alpha_{2}\begin{pmatrix}
|
||||
0 \\
|
||||
1
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<p>Let us call <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msub><mi>α</mi><mn>1</mn></msub><annotation encoding="application/x-tex">\alpha_{1}</annotation></semantics></math> and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msub><mi>α</mi><mn>2</mn></msub><annotation encoding="application/x-tex">\alpha_{2}</annotation></semantics></math> the <em>coordinates</em> of the
|
||||
vector. Then, we can write <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>v</mi><annotation encoding="application/x-tex">v</annotation></semantics></math> as</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>=</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><msub><mi>α</mi><mn>1</mn></msub></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><msub><mi>α</mi><mn>2</mn></msub></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">v = \begin{pmatrix}
|
||||
\alpha_{1} \\
|
||||
\alpha_{2}
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<p>For example, the vector</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>2</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
1 \\
|
||||
2
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<p>represents</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>⋅</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>+</mo><mn>2</mn><mo>⋅</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">1 \cdot \begin{pmatrix}
|
||||
1 \\
|
||||
0
|
||||
\end{pmatrix} + 2 \cdot \begin{pmatrix}
|
||||
0 \\
|
||||
1
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<p>Verify that this aligns with your previous intuition of vectors.</p>
|
||||
<p>You may recognize the standard basis in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mn>2</mn></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{2}</annotation></semantics></math> as the
|
||||
familiar unit vectors</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover><mi>i</mi><mo accent="true">̂</mo></mover><mo>,</mo><mover><mi>j</mi><mo accent="true">̂</mo></mover></mrow><annotation encoding="application/x-tex">\hat{i},\hat{j}</annotation></semantics></math></p>
|
||||
<p>This aligns with the fact that</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mi>α</mi></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mi>β</mi></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mi>α</mi><mover><mi>i</mi><mo accent="true">̂</mo></mover><mo>+</mo><mi>β</mi><mover><mi>j</mi><mo accent="true">̂</mo></mover></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
\alpha \\
|
||||
\beta
|
||||
\end{pmatrix} = \alpha\hat{i} + \beta\hat{j}</annotation></semantics></math></p>
|
||||
<p>However, we may define a standard basis in any arbitrary vector space.
|
||||
So, let</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub><mo>,</mo><msub><mi>e</mi><mn>2</mn></msub><mo>,</mo><mi>…</mi><mo>,</mo><msub><mi>e</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">e_{1},e_{2},\ldots,e_{n}</annotation></semantics></math></p>
|
||||
<p>be a standard basis in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>𝔽</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{F}}^{n}</annotation></semantics></math>. Then, the coordinates
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>1</mn></msub><mo>,</mo><msub><mi>α</mi><mn>2</mn></msub><mo>,</mo><mi>…</mi><mo>,</mo><msub><mi>α</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">\alpha_{1},\alpha_{2},\ldots,\alpha_{n}</annotation></semantics></math> of a vector
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>∈</mo><msup><mi>𝔽</mi><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">v \in {\mathbb{F}}^{n}</annotation></semantics></math> represent the following</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><msub><mi>α</mi><mn>1</mn></msub></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><msub><mi>α</mi><mn>2</mn></msub></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mi>⋮</mi></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><msub><mi>α</mi><mi>n</mi></msub></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><msub><mi>α</mi><mn>1</mn></msub><msub><mi>e</mi><mn>1</mn></msub><mo>+</mo><msub><mi>α</mi><mn>2</mn></msub><mo>+</mo><msub><mi>e</mi><mn>2</mn></msub><mo>+</mo><msub><mi>α</mi><mi>n</mi></msub><msub><mi>e</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
\alpha_{1} \\
|
||||
\alpha_{2} \\
|
||||
\vdots \\
|
||||
\alpha_{n}
|
||||
\end{pmatrix} = \alpha_{1}e_{1} + \alpha_{2} + e_{2} + \alpha_{n}e_{n}</annotation></semantics></math></p>
|
||||
<p>Using our new notation, the standard basis in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mn>2</mn></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{2}</annotation></semantics></math> is</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub><mo>=</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>,</mo><msub><mi>e</mi><mn>2</mn></msub><mo>=</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">e_{1} = \begin{pmatrix}
|
||||
1 \\
|
||||
0
|
||||
\end{pmatrix},e_{2} = \begin{pmatrix}
|
||||
0 \\
|
||||
1
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<h2 id="matrices">Matrices</h2>
|
||||
<p>Before discussing any properties of matrices, let’s simply reiterate
|
||||
what we learned in class about their notation. We say a matrix with rows
|
||||
of length <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>m</mi><annotation encoding="application/x-tex">m</annotation></semantics></math>, and columns of size <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>n</mi><annotation encoding="application/x-tex">n</annotation></semantics></math> (in less precise terms, a matrix
|
||||
with length <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>m</mi><annotation encoding="application/x-tex">m</annotation></semantics></math> and height <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>n</mi><annotation encoding="application/x-tex">n</annotation></semantics></math>) is a <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mo>×</mo><mi>n</mi></mrow><annotation encoding="application/x-tex">m \times n</annotation></semantics></math> matrix.</p>
|
||||
<p>Given a matrix</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>=</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>2</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>3</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>4</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>5</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>6</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>7</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>8</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>9</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">A = \begin{pmatrix}
|
||||
1 & 2 & 3 \\
|
||||
4 & 5 & 6 \\
|
||||
7 & 8 & 9
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<p>we refer to the entry in row <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>j</mi><annotation encoding="application/x-tex">j</annotation></semantics></math> and column <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>k</mi><annotation encoding="application/x-tex">k</annotation></semantics></math> as <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msub><mi>A</mi><mrow><mi>j</mi><mo>,</mo><mi>k</mi></mrow></msub><annotation encoding="application/x-tex">A_{j,k}</annotation></semantics></math> .</p>
|
||||
<h3 id="matrix-transpose">Matrix transpose</h3>
|
||||
<p>A formalism that is useful later on is called the <em>transpose</em>, and we
|
||||
obtain it from a matrix <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>A</mi><annotation encoding="application/x-tex">A</annotation></semantics></math> by switching all the rows and columns. More
|
||||
precisely, each row becomes a column instead. We use the notation
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>A</mi><mi>T</mi></msup><annotation encoding="application/x-tex">A^{T}</annotation></semantics></math> to represent the transpose of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>A</mi><annotation encoding="application/x-tex">A</annotation></semantics></math>.</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>2</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>3</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>4</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>5</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>6</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mi>T</mi></msup><mo>=</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>4</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>2</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>5</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>3</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>6</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
1 & 2 & 3 \\
|
||||
4 & 5 & 6
|
||||
\end{pmatrix}^{T} = \begin{pmatrix}
|
||||
1 & 4 \\
|
||||
2 & 5 \\
|
||||
3 & 6
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<p>Formally, we can say <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mrow><mo stretchy="true" form="prefix">(</mo><msup><mi>A</mi><mi>T</mi></msup><mo stretchy="true" form="postfix">)</mo></mrow><mrow><mi>j</mi><mo>,</mo><mi>k</mi></mrow></msub><mo>=</mo><msub><mi>A</mi><mrow><mi>k</mi><mo>,</mo><mi>j</mi></mrow></msub></mrow><annotation encoding="application/x-tex">\left( A^{T} \right)_{j,k} = A_{k,j}</annotation></semantics></math></p>
|
||||
<h2 id="linear-transformations">Linear transformations</h2>
|
||||
<p>A linear transformation <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo>:</mo><mi>V</mi><mo>→</mo><mi>W</mi></mrow><annotation encoding="application/x-tex">T:V \rightarrow W</annotation></semantics></math> is a mapping between two
|
||||
vector spaces <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>V</mi><mo>→</mo><mi>W</mi></mrow><annotation encoding="application/x-tex">V \rightarrow W</annotation></semantics></math>, such that the following axioms are
|
||||
satisfied:</p>
|
||||
<ol>
|
||||
<li><p><math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>v</mi><mo>+</mo><mi>w</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mi>T</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>v</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>+</mo><mi>T</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>w</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>,</mo><mo>∀</mo><mi>v</mi><mo>∈</mo><mi>V</mi><mo>,</mo><mo>∀</mo><mi>w</mi><mo>∈</mo><mi>W</mi></mrow><annotation encoding="application/x-tex">T(v + w) = T(v) + T(w),\forall v \in V,\forall w \in W</annotation></semantics></math></p></li>
|
||||
<li><p><math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>α</mi><mi>v</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>+</mo><mi>T</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>β</mi><mi>w</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mi>α</mi><mi>T</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>v</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>+</mo><mi>β</mi><mi>T</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>w</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>,</mo><mo>∀</mo><mi>v</mi><mo>∈</mo><mi>V</mi><mo>,</mo><mo>∀</mo><mi>w</mi><mo>∈</mo><mi>W</mi></mrow><annotation encoding="application/x-tex">T(\alpha v) + T(\beta w) = \alpha T(v) + \beta T(w),\forall v \in V,\forall w \in W</annotation></semantics></math>,
|
||||
for all scalars <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>,</mo><mi>β</mi></mrow><annotation encoding="application/x-tex">\alpha,\beta</annotation></semantics></math></p></li>
|
||||
</ol>
|
||||
<p><em>Definition</em>. <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>T</mi><annotation encoding="application/x-tex">T</annotation></semantics></math> is a linear transformation iff.</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>α</mi><mi>v</mi><mo>+</mo><mi>β</mi><mi>w</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mi>α</mi><mi>T</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>v</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>+</mo><mi>β</mi><mi>T</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>w</mi><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">T(\alpha v + \beta w) = \alpha T(v) + \beta T(w)</annotation></semantics></math></p>
|
||||
<p><em>Abuse of notation</em>. From now on, we may elide the parentheses and say
|
||||
that <math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mrow><mo stretchy="true" form="prefix">(</mo><mi>v</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mi>T</mi><mi>v</mi><mo>,</mo><mo>∀</mo><mi>v</mi><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">T(v) = Tv,\forall v \in V</annotation></semantics></math></p>
|
||||
<p><em>Remark</em>. A phrase that you may commonly hear is that linear
|
||||
transformations preserve <em>linearity</em>. Essentially, straight lines remain
|
||||
straight, parallel lines remain parallel, and the origin remains fixed
|
||||
at 0. Take a moment to think about why this is true (at least, in lower
|
||||
dimensional spaces you can visualize).</p>
|
||||
<p><em>Examples</em>.</p>
|
||||
<ol>
|
||||
<li><p>Rotation for <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>V</mi><mo>=</mo><mi>W</mi><mo>=</mo><msup><mi>ℝ</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">V = W = {\mathbb{R}}^{2}</annotation></semantics></math> (i.e. rotation in 2
|
||||
dimensions). Given <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>,</mo><mi>w</mi><mo>∈</mo><msup><mi>ℝ</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">v,w \in {\mathbb{R}}^{2}</annotation></semantics></math>, and their linear
|
||||
combination <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>+</mo><mi>w</mi></mrow><annotation encoding="application/x-tex">v + w</annotation></semantics></math>, a rotation of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>γ</mi><annotation encoding="application/x-tex">\gamma</annotation></semantics></math> radians of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>+</mo><mi>w</mi></mrow><annotation encoding="application/x-tex">v + w</annotation></semantics></math> is
|
||||
equivalent to first rotating <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>v</mi><annotation encoding="application/x-tex">v</annotation></semantics></math> and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>w</mi><annotation encoding="application/x-tex">w</annotation></semantics></math> individually by <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>γ</mi><annotation encoding="application/x-tex">\gamma</annotation></semantics></math>
|
||||
and then taking their linear combination.</p></li>
|
||||
<li><p>Differentiation of polynomials. In this case <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>V</mi><mo>=</mo><msup><mi>ℙ</mi><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">V = {\mathbb{P}}^{n}</annotation></semantics></math>
|
||||
and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>W</mi><mo>=</mo><msup><mi>ℙ</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msup></mrow><annotation encoding="application/x-tex">W = {\mathbb{P}}^{n - 1}</annotation></semantics></math>, where <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℙ</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{P}}^{n}</annotation></semantics></math> is the
|
||||
field of all polynomials of degree at most <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>n</mi><annotation encoding="application/x-tex">n</annotation></semantics></math>.</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mi>d</mi><mrow><mi>d</mi><mi>x</mi></mrow></mfrac><mrow><mo stretchy="true" form="prefix">(</mo><mi>α</mi><mi>v</mi><mo>+</mo><mi>β</mi><mi>w</mi><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mi>α</mi><mfrac><mi>d</mi><mrow><mi>d</mi><mi>x</mi></mrow></mfrac><mi>v</mi><mo>+</mo><mi>β</mi><mfrac><mi>d</mi><mrow><mi>d</mi><mi>x</mi></mrow></mfrac><mi>w</mi><mo>,</mo><mo>∀</mo><mi>v</mi><mo>∈</mo><mi>V</mi><mo>,</mo><mi>w</mi><mo>∈</mo><mi>W</mi><mo>,</mo><mo>∀</mo><mrow><mspace width="0.333em"></mspace><mtext mathvariant="normal"> scalars </mtext><mspace width="0.333em"></mspace></mrow><mi>α</mi><mo>,</mo><mi>β</mi></mrow><annotation encoding="application/x-tex">\frac{d}{dx}(\alpha v + \beta w) = \alpha\frac{d}{dx}v + \beta\frac{d}{dx}w,\forall v \in V,w \in W,\forall\text{ scalars }\alpha,\beta</annotation></semantics></math></p></li>
|
||||
</ol>
|
||||
<h2 id="matrices-represent-linear-transformations">Matrices represent linear transformations</h2>
|
||||
<p>Suppose we wanted to represent a linear transformation
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo>:</mo><msup><mi>𝔽</mi><mi>n</mi></msup><mo>→</mo><msup><mi>𝔽</mi><mi>m</mi></msup></mrow><annotation encoding="application/x-tex">T:{\mathbb{F}}^{n} \rightarrow {\mathbb{F}}^{m}</annotation></semantics></math>. I propose that we
|
||||
need encode how <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>T</mi><annotation encoding="application/x-tex">T</annotation></semantics></math> acts on the standard basis of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>𝔽</mi><mi>n</mi></msup><annotation encoding="application/x-tex">{\mathbb{F}}^{n}</annotation></semantics></math>.</p>
|
||||
<p>Using our intuition from lower dimensional vector spaces, we know that
|
||||
the standard basis in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mn>2</mn></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{2}</annotation></semantics></math> is the unit vectors <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mover><mi>i</mi><mo accent="true">̂</mo></mover><annotation encoding="application/x-tex">\hat{i}</annotation></semantics></math>
|
||||
and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mover><mi>j</mi><mo accent="true">̂</mo></mover><annotation encoding="application/x-tex">\hat{j}</annotation></semantics></math>. Because linear transformations preserve linearity (i.e.
|
||||
all straight lines remain straight and parallel lines remain parallel),
|
||||
we can encode any transformation as simply changing <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mover><mi>i</mi><mo accent="true">̂</mo></mover><annotation encoding="application/x-tex">\hat{i}</annotation></semantics></math> and
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mover><mi>j</mi><mo accent="true">̂</mo></mover><annotation encoding="application/x-tex">\hat{j}</annotation></semantics></math>. And indeed, if any vector <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>∈</mo><msup><mi>ℝ</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">v \in {\mathbb{R}}^{2}</annotation></semantics></math> can be
|
||||
represented as the linear combination of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mover><mi>i</mi><mo accent="true">̂</mo></mover><annotation encoding="application/x-tex">\hat{i}</annotation></semantics></math> and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mover><mi>j</mi><mo accent="true">̂</mo></mover><annotation encoding="application/x-tex">\hat{j}</annotation></semantics></math> (this
|
||||
is the definition of a basis), it makes sense both symbolically and
|
||||
geometrically that we can represent all linear transformations as the
|
||||
transformations of the basis vectors.</p>
|
||||
<p><em>Example</em>. To reflect all vectors <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>∈</mo><msup><mi>ℝ</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">v \in {\mathbb{R}}^{2}</annotation></semantics></math> across the
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>y</mi><annotation encoding="application/x-tex">y</annotation></semantics></math>-axis, we can simply change the standard basis to</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mi>−</mi><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
- 1 \\
|
||||
0
|
||||
\end{pmatrix}\begin{pmatrix}
|
||||
0 \\
|
||||
1
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<p>Then, any vector in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mn>2</mn></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{2}</annotation></semantics></math> using this new basis will be
|
||||
reflected across the <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>y</mi><annotation encoding="application/x-tex">y</annotation></semantics></math>-axis. Take a moment to justify this
|
||||
geometrically.</p>
|
||||
<h3 id="writing-a-linear-transformation-as-matrix">Writing a linear transformation as matrix</h3>
|
||||
<p>For any linear transformation
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo>:</mo><msup><mi>𝔽</mi><mi>m</mi></msup><mo>→</mo><msup><mi>𝔽</mi><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">T:{\mathbb{F}}^{m} \rightarrow {\mathbb{F}}^{n}</annotation></semantics></math>, we can write it as an
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>×</mo><mi>m</mi></mrow><annotation encoding="application/x-tex">n \times m</annotation></semantics></math> matrix <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>A</mi><annotation encoding="application/x-tex">A</annotation></semantics></math>. That is, there is a matrix <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>A</mi><annotation encoding="application/x-tex">A</annotation></semantics></math> with <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>n</mi><annotation encoding="application/x-tex">n</annotation></semantics></math> rows
|
||||
and <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>m</mi><annotation encoding="application/x-tex">m</annotation></semantics></math> columns that can represent any linear transformation from
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>𝔽</mi><mi>m</mi></msup><mo>→</mo><msup><mi>𝔽</mi><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">{\mathbb{F}}^{m} \rightarrow {\mathbb{F}}^{n}</annotation></semantics></math>.</p>
|
||||
<p>How should we write this matrix? Naturally, from our previous
|
||||
discussion, we should write a matrix with each <em>column</em> being one of our
|
||||
new transformed <em>basis</em> vectors.</p>
|
||||
<p><em>Example</em>. Our <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>y</mi><annotation encoding="application/x-tex">y</annotation></semantics></math>-axis reflection transformation from earlier. We write
|
||||
the bases in a matrix</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mi>−</mi><mn>1</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
- 1 & 0 \\
|
||||
0 & 1
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<h3 id="matrix-vector-multiplication">Matrix-vector multiplication</h3>
|
||||
<p>Perhaps you now see why the so-called matrix-vector multiplication is
|
||||
defined the way it is. Recalling our definition of a basis, given a
|
||||
basis in <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>V</mi><annotation encoding="application/x-tex">V</annotation></semantics></math>, any vector <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>v</mi><mo>∈</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">v \in V</annotation></semantics></math> can be written as the linear
|
||||
combination of the vectors in the basis. Then, given a linear
|
||||
transformation represented by the matrix containing the new basis, we
|
||||
simply write the linear combination with the new basis instead.</p>
|
||||
<p><em>Example</em>. Let us first write a vector in the standard basis in
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>ℝ</mi><mn>2</mn></msup><annotation encoding="application/x-tex">{\mathbb{R}}^{2}</annotation></semantics></math> and then show how our matrix-vector multiplication
|
||||
naturally corresponds to the definition of the linear transformation.</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>2</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>∈</mo><msup><mi>ℝ</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
1 \\
|
||||
2
|
||||
\end{pmatrix} \in {\mathbb{R}}^{2}</annotation></semantics></math></p>
|
||||
<p>is the same as</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>⋅</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>+</mo><mn>2</mn><mo>⋅</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">1 \cdot \begin{pmatrix}
|
||||
1 \\
|
||||
0
|
||||
\end{pmatrix} + 2 \cdot \begin{pmatrix}
|
||||
0 \\
|
||||
1
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<p>Then, to perform our reflection, we need only replace the basis vector
|
||||
<math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
1 \\
|
||||
0
|
||||
\end{pmatrix}</annotation></semantics></math> with <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mi>−</mi><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
- 1 \\
|
||||
0
|
||||
\end{pmatrix}</annotation></semantics></math>.</p>
|
||||
<p>Then, the reflected vector is given by</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>⋅</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mi>−</mi><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>+</mo><mn>2</mn><mo>⋅</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>=</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mi>−</mi><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>2</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">1 \cdot \begin{pmatrix}
|
||||
- 1 \\
|
||||
0
|
||||
\end{pmatrix} + 2 \cdot \begin{pmatrix}
|
||||
0 \\
|
||||
1
|
||||
\end{pmatrix} = \begin{pmatrix}
|
||||
- 1 \\
|
||||
2
|
||||
\end{pmatrix}</annotation></semantics></math></p>
|
||||
<p>We can clearly see that this is exactly how the matrix multiplication</p>
|
||||
<p><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mi>−</mi><mn>1</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>0</mn></mtd><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow><mo>⋅</mo><mrow><mo stretchy="true" form="prefix">(</mo><mtable><mtr><mtd columnalign="center" style="text-align: center"><mn>1</mn></mtd></mtr><mtr><mtd columnalign="center" style="text-align: center"><mn>2</mn></mtd></mtr></mtable><mo stretchy="true" form="postfix">)</mo></mrow></mrow><annotation encoding="application/x-tex">\begin{pmatrix}
|
||||
- 1 & 0 \\
|
||||
0 & 1
|
||||
\end{pmatrix} \cdot \begin{pmatrix}
|
||||
1 \\
|
||||
2
|
||||
\end{pmatrix}</annotation></semantics></math> is defined! The <em>column-by-coordinate</em> rule for
|
||||
matrix-vector multiplication says that we multiply the <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>n</mi><mtext mathvariant="normal">th</mtext></msup><annotation encoding="application/x-tex">n^{\text{th}}</annotation></semantics></math>
|
||||
entry of the vector by the corresponding <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><msup><mi>n</mi><mtext mathvariant="normal">th</mtext></msup><annotation encoding="application/x-tex">n^{\text{th}}</annotation></semantics></math> column of the
|
||||
matrix and sum them all up (take their linear combination). This
|
||||
algorithm intuitively follows from our definition of matrices.</p>
|
||||
<h3 id="matrix-matrix-multiplication">Matrix-matrix multiplication</h3>
|
||||
<p>As you may have noticed, a very similar natural definition arises for
|
||||
the <em>matrix-matrix</em> multiplication. Multiplying two matrices <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>⋅</mo><mi>B</mi></mrow><annotation encoding="application/x-tex">A \cdot B</annotation></semantics></math>
|
||||
is essentially just taking each column of <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>B</mi><annotation encoding="application/x-tex">B</annotation></semantics></math>, and applying the linear
|
||||
transformation defined by the matrix <math display="inline" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mi>A</mi><annotation encoding="application/x-tex">A</annotation></semantics></math>!</p></main>
|
||||
</article>
|
||||
|
||||
<footer class="mt-14 md:mt-24 pb-12 font-light">
|
||||
<hr
|
||||
class="border-0 dark:bg-muted-dark bg-muted-light rounded-xl h-0.5 mb-4"
|
||||
/>
|
||||
<p class="text-sm leading-relaxed">
|
||||
© 2024 Youwen Wu. Generated by
|
||||
<a
|
||||
href="https://jaspervdj.be/hakyll/"
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
>Hakyll.</a
|
||||
>
|
||||
View the source
|
||||
<a
|
||||
href="https://github.com/couscousdude/blog"
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
>on GitHub.</a
|
||||
>
|
||||
</p>
|
||||
<p class="text-sm leading-relaxed mt-2">
|
||||
Content freely available under
|
||||
<a
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en"
|
||||
><span class="smallcaps">CC BY-NC-SA</span> 4.0</a
|
||||
>
|
||||
unless otherwise noted.
|
||||
</p>
|
||||
</footer>
|
||||
<script defer src="./out/bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
1
css/code.css
Normal file
1
css/code.css
Normal file
|
@ -0,0 +1 @@
|
|||
pre>code.sourceCode{white-space:pre;position:relative}pre>code.sourceCode>span{line-height:1.25}pre>code.sourceCode>span:empty{height:1.2em}.sourceCode{overflow:visible}code.sourceCode>span{color:inherit;text-decoration:inherit}div.sourceCode{margin:1em 0}pre.sourceCode{margin:0}@media screen{div.sourceCode{overflow:auto}}@media print{pre>code.sourceCode{white-space:pre-wrap}pre>code.sourceCode>span{display:inline-block;text-indent:-5em;padding-left:5em}}pre.numberSource code{counter-reset:source-line 0}pre.numberSource code>span{position:relative;left:-4em;counter-increment:source-line}pre.numberSource code>span>a:first-child::before{content:counter(source-line);position:relative;left:-1em;text-align:right;vertical-align:baseline;border:none;display:inline-block;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:0 4px;width:4em;background-color:#232629;color:#7a7c7d}pre.numberSource{margin-left:3em;border-left:1px solid #7a7c7d;padding-left:4px}div.sourceCode{color:#cfcfc2;background-color:#232629}@media screen{pre>code.sourceCode>span>a:first-child::before{text-decoration:underline}}code span{color:#cfcfc2}code span.al{color:#95da4c;background-color:#4d1f24;font-weight:bold}code span.an{color:#3f8058}code span.at{color:#2980b9}code span.bn{color:#f67400}code span.bu{color:#7f8c8d}code span.cf{color:#fdbc4b;font-weight:bold}code span.ch{color:#3daee9}code span.cn{color:#27aeae;font-weight:bold}code span.co{color:#7a7c7d}code span.cv{color:#7f8c8d}code span.do{color:#a43340}code span.dt{color:#2980b9}code span.dv{color:#f67400}code span.er{color:#da4453;text-decoration:underline}code span.ex{color:#0099ff;font-weight:bold}code span.fl{color:#f67400}code span.fu{color:#8e44ad}code span.im{color:#27ae60}code span.in{color:#c45b00}code span.kw{color:#cfcfc2;font-weight:bold}code span.op{color:#cfcfc2}code span.ot{color:#27ae60}code span.pp{color:#27ae60}code span.re{color:#2980b9;background-color:#153042}code span.sc{color:#3daee9}code span.ss{color:#da4453}code span.st{color:#f44f4f}code span.va{color:#27aeae}code span.vs{color:#da4453}code span.wa{color:#da4453}
|
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
BIN
images/conditional-finality.png
Normal file
BIN
images/conditional-finality.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
260
index.html
Normal file
260
index.html
Normal file
|
@ -0,0 +1,260 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>youwen wu | The Involution</title>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="a weblog about computers, math, hacks, games, and life" />
|
||||
|
||||
|
||||
<meta property="og:site_name" content="The Involution" />
|
||||
<meta property="og:title" content="youwen wu" />
|
||||
<meta property="og:url" content="https://blog.youwen.dev/index.html" />
|
||||
<meta property="og:description" content="a weblog about computers, math, hacks, games, and life" />
|
||||
|
||||
<meta property="og:image" content="https://blog.youwen.dev./images/gradient-ascent.jpg" />
|
||||
|
||||
<meta property="og:type" content="website" />
|
||||
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:image" content="https://blog.youwen.dev./images/gradient-ascent.jpg" />
|
||||
|
||||
<meta property="twitter:site" content="The Involution" />
|
||||
<meta property="twitter:title" content="youwen wu" />
|
||||
<meta property="twitter:description" content="a weblog about computers, math, hacks, games, and life" />
|
||||
|
||||
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="canonical" href="https://blog.youwen.dev/index.html" />
|
||||
|
||||
<link
|
||||
rel="alternate"
|
||||
href="./atom.xml"
|
||||
title="The Involution"
|
||||
type="application/atom+xml"
|
||||
/>
|
||||
<link
|
||||
rel="alternate"
|
||||
href="./rss.xml"
|
||||
title="The Involution"
|
||||
type="application/rss+xml"
|
||||
/>
|
||||
<link rel="stylesheet" href="./out/bundle.css" />
|
||||
<link rel="stylesheet" href="./css/code.css" />
|
||||
<script
|
||||
defer
|
||||
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/mml-chtml.js"
|
||||
></script>
|
||||
|
||||
<script>
|
||||
if (
|
||||
localStorage.theme === "dark" ||
|
||||
(!("theme" in localStorage) &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches)
|
||||
) {
|
||||
document.documentElement.classList.add("dark")
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark")
|
||||
}
|
||||
window.onload = () => {
|
||||
var themeButton = document.getElementById("theme-toggle")
|
||||
const theme = localStorage.getItem("theme")
|
||||
if (theme === "light") {
|
||||
themeButton.innerText = "theme: light"
|
||||
} else if (theme === "dark") {
|
||||
themeButton.innerText = "theme: dark"
|
||||
} else {
|
||||
themeButton.innerText = "theme: system"
|
||||
}
|
||||
var fontButton = document.getElementById("font-toggle")
|
||||
const font = localStorage.getItem("font")
|
||||
if (font && font === "serif") {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
document.body.classList.add("font-serif")
|
||||
fontButton.innerText = "serif"
|
||||
}
|
||||
if (font && font === "sans") {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
document.body.classList.add("font-sans")
|
||||
fontButton.innerText = "sans"
|
||||
}
|
||||
if (!font) {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
fontButton.innerText = "serif"
|
||||
}
|
||||
}
|
||||
MathJax = {
|
||||
startup: {
|
||||
ready: function () {
|
||||
MathJax.startup.defaultReady()
|
||||
MathJax.startup.promise.then(function () {
|
||||
MathJax.mathml2svgPromise(document.body)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body
|
||||
class="container max-w-3xl mx-auto px-4 transition-colors duration-[2s]"
|
||||
>
|
||||
<header class="mt-14 md:mt-24 mb-14">
|
||||
<div class="inline-flex items-center w-full">
|
||||
<h1 class="text-4xl md:text-5xl font-serif font-medium">
|
||||
<a
|
||||
href="/"
|
||||
class="dark:hover:text-muted-dark hover:text-muted-light transition-all duration-500 text-nowrap tracking-wide"
|
||||
><em>The Involution.</em></a
|
||||
>
|
||||
</h1>
|
||||
<div
|
||||
class="w-full flex-grow flex-shrink rounded-lg h-1 bg-muted-light dark:bg-muted-dark mx-4"
|
||||
></div>
|
||||
</div>
|
||||
<p class="mt-8 mb-3 px-1 italic font-light">
|
||||
a web-log about computers and math and hacking.
|
||||
</p>
|
||||
<a class="text-sm text-iris-light dark:text-iris-dark hover:text-love-light dark:hover:text-love-dark" href="https://youwen.dev"
|
||||
><em>by </em>Youwen Wu</a
|
||||
>
|
||||
<span class="ml-2 font-serif">|</span>
|
||||
<button
|
||||
id="theme-toggle"
|
||||
class="ml-2 text-sm hover:text-accent-light dark:hover:text-muted-dark"
|
||||
></button>
|
||||
<span class="ml-2 font-serif">|</span>
|
||||
<button
|
||||
id="font-toggle"
|
||||
class="ml-2 text-sm hover:text-accent-light dark:hover:text-muted-dark"
|
||||
></button>
|
||||
</header>
|
||||
<main>
|
||||
<section>
|
||||
<h2 class="text-3xl">Latest</h2>
|
||||
<hr
|
||||
class="sm:mr-2 max-w-sm border-0 h-0.5 dark:bg-muted-dark bg-muted-light rounded-md mt-2"
|
||||
/>
|
||||
<ul class="mt-6 space-y-4 md:space-y-8">
|
||||
|
||||
<li class="group">
|
||||
<div class="rounded-md p-2">
|
||||
<a
|
||||
href="./random-variables-distributions-and-probability-theory.html"
|
||||
class="w-fit dark:group-hover:text-iris-dark group-hover:text-iris-light transition-colors"
|
||||
>
|
||||
<h3 class="text-2xl">Random variables, distributions, and probability theory</h3>
|
||||
<p
|
||||
class="italic text-accent-light dark:text-accent-dark my-1 group-hover:dark:text-muted-dark group-hover:text-muted-light transition-colors"
|
||||
>
|
||||
An overview of discrete and continuous random variables and their distributions and moment generating functions
|
||||
</p>
|
||||
<p class="text-sm">2025-02-16</p>
|
||||
</a>
|
||||
</div>
|
||||
<hr
|
||||
class="max-w-[200px] border-0 h-1 dark:bg-accent-dark bg-accent-light rounded-lg px-2 group-hover:max-w-[250px] dark:group-hover:bg-iris-dark group-hover:bg-iris-light transition-all duration-400"
|
||||
/>
|
||||
</li>
|
||||
|
||||
<li class="group">
|
||||
<div class="rounded-md p-2">
|
||||
<a
|
||||
href="./an-assortment-of-preliminaries-on-linear-algebra.html"
|
||||
class="w-fit dark:group-hover:text-iris-dark group-hover:text-iris-light transition-colors"
|
||||
>
|
||||
<h3 class="text-2xl">An assortment of preliminaries on linear algebra</h3>
|
||||
<p
|
||||
class="italic text-accent-light dark:text-accent-dark my-1 group-hover:dark:text-muted-dark group-hover:text-muted-light transition-colors"
|
||||
>
|
||||
and also a test for pandoc
|
||||
</p>
|
||||
<p class="text-sm">2025-02-15</p>
|
||||
</a>
|
||||
</div>
|
||||
<hr
|
||||
class="max-w-[200px] border-0 h-1 dark:bg-accent-dark bg-accent-light rounded-lg px-2 group-hover:max-w-[250px] dark:group-hover:bg-iris-dark group-hover:bg-iris-light transition-all duration-400"
|
||||
/>
|
||||
</li>
|
||||
|
||||
<li class="group">
|
||||
<div class="rounded-md p-2">
|
||||
<a
|
||||
href="./nix-automatic-hash-updates-made-easy.html"
|
||||
class="w-fit dark:group-hover:text-iris-dark group-hover:text-iris-light transition-colors"
|
||||
>
|
||||
<h3 class="text-2xl">Nix automatic hash updates made easy</h3>
|
||||
<p
|
||||
class="italic text-accent-light dark:text-accent-dark my-1 group-hover:dark:text-muted-dark group-hover:text-muted-light transition-colors"
|
||||
>
|
||||
keep your flakes up to date
|
||||
</p>
|
||||
<p class="text-sm">2024-12-28</p>
|
||||
</a>
|
||||
</div>
|
||||
<hr
|
||||
class="max-w-[200px] border-0 h-1 dark:bg-accent-dark bg-accent-light rounded-lg px-2 group-hover:max-w-[250px] dark:group-hover:bg-iris-dark group-hover:bg-iris-light transition-all duration-400"
|
||||
/>
|
||||
</li>
|
||||
|
||||
<li class="group">
|
||||
<div class="rounded-md p-2">
|
||||
<a
|
||||
href="./a-haskellian-blog.html"
|
||||
class="w-fit dark:group-hover:text-iris-dark group-hover:text-iris-light transition-colors"
|
||||
>
|
||||
<h3 class="text-2xl">a haskellian blog</h3>
|
||||
<p
|
||||
class="italic text-accent-light dark:text-accent-dark my-1 group-hover:dark:text-muted-dark group-hover:text-muted-light transition-colors"
|
||||
>
|
||||
a purely functional...blog?
|
||||
</p>
|
||||
<p class="text-sm">2024-05-25</p>
|
||||
</a>
|
||||
</div>
|
||||
<hr
|
||||
class="max-w-[200px] border-0 h-1 dark:bg-accent-dark bg-accent-light rounded-lg px-2 group-hover:max-w-[250px] dark:group-hover:bg-iris-dark group-hover:bg-iris-light transition-all duration-400"
|
||||
/>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer class="mt-14 md:mt-24 pb-12 font-light">
|
||||
<hr
|
||||
class="border-0 dark:bg-muted-dark bg-muted-light rounded-xl h-0.5 mb-4"
|
||||
/>
|
||||
<p class="text-sm leading-relaxed">
|
||||
© 2024 Youwen Wu. Generated by
|
||||
<a
|
||||
href="https://jaspervdj.be/hakyll/"
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
>Hakyll.</a
|
||||
>
|
||||
View the source
|
||||
<a
|
||||
href="https://github.com/couscousdude/blog"
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
>on GitHub.</a
|
||||
>
|
||||
</p>
|
||||
<p class="text-sm leading-relaxed mt-2">
|
||||
Content freely available under
|
||||
<a
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en"
|
||||
><span class="smallcaps">CC BY-NC-SA</span> 4.0</a
|
||||
>
|
||||
unless otherwise noted.
|
||||
</p>
|
||||
</footer>
|
||||
<script defer src="./out/bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
435
nix-automatic-hash-updates-made-easy.html
Normal file
435
nix-automatic-hash-updates-made-easy.html
Normal file
|
@ -0,0 +1,435 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Nix automatic hash updates made easy | The Involution</title>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="keep your flakes up to date" />
|
||||
|
||||
<meta name="author" content="Youwen Wu" />
|
||||
|
||||
<meta name="keywords" content="nix, update, zen browser" />
|
||||
|
||||
|
||||
<meta property="og:site_name" content="The Involution" />
|
||||
<meta property="og:title" content="Nix automatic hash updates made easy" />
|
||||
<meta property="og:url" content="https://blog.youwen.dev/nix-automatic-hash-updates-made-easy.html" />
|
||||
<meta property="og:description" content="keep your flakes up to date" />
|
||||
|
||||
<meta property="og:image" content="https://blog.youwen.devhttps://wallpapercave.com/wp/wp12329537.png" />
|
||||
|
||||
<meta property="og:type" content="article" />
|
||||
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:image" content="https://blog.youwen.devhttps://wallpapercave.com/wp/wp12329537.png" />
|
||||
|
||||
<meta property="twitter:site" content="The Involution" />
|
||||
<meta property="twitter:title" content="Nix automatic hash updates made easy" />
|
||||
<meta property="twitter:description" content="keep your flakes up to date" />
|
||||
|
||||
<meta property="twitter:creator" content="@youwen" />
|
||||
|
||||
|
||||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="canonical" href="https://blog.youwen.dev/nix-automatic-hash-updates-made-easy.html" />
|
||||
|
||||
<link
|
||||
rel="alternate"
|
||||
href="./atom.xml"
|
||||
title="The Involution"
|
||||
type="application/atom+xml"
|
||||
/>
|
||||
<link
|
||||
rel="alternate"
|
||||
href="./rss.xml"
|
||||
title="The Involution"
|
||||
type="application/rss+xml"
|
||||
/>
|
||||
<link rel="stylesheet" href="./out/bundle.css" />
|
||||
<link rel="stylesheet" href="./css/code.css" />
|
||||
<script
|
||||
defer
|
||||
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/mml-chtml.js"
|
||||
></script>
|
||||
|
||||
<script>
|
||||
if (
|
||||
localStorage.theme === "dark" ||
|
||||
(!("theme" in localStorage) &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches)
|
||||
) {
|
||||
document.documentElement.classList.add("dark")
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark")
|
||||
}
|
||||
window.onload = () => {
|
||||
var themeButton = document.getElementById("theme-toggle")
|
||||
const theme = localStorage.getItem("theme")
|
||||
if (theme === "light") {
|
||||
themeButton.innerText = "theme: light"
|
||||
} else if (theme === "dark") {
|
||||
themeButton.innerText = "theme: dark"
|
||||
} else {
|
||||
themeButton.innerText = "theme: system"
|
||||
}
|
||||
var fontButton = document.getElementById("font-toggle")
|
||||
const font = localStorage.getItem("font")
|
||||
if (font && font === "serif") {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
document.body.classList.add("font-serif")
|
||||
fontButton.innerText = "serif"
|
||||
}
|
||||
if (font && font === "sans") {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
document.body.classList.add("font-sans")
|
||||
fontButton.innerText = "sans"
|
||||
}
|
||||
if (!font) {
|
||||
document.body.classList.remove("font-sans")
|
||||
document.body.classList.remove("font-serif")
|
||||
fontButton.innerText = "serif"
|
||||
}
|
||||
}
|
||||
MathJax = {
|
||||
startup: {
|
||||
ready: function () {
|
||||
MathJax.startup.defaultReady()
|
||||
MathJax.startup.promise.then(function () {
|
||||
MathJax.mathml2svgPromise(document.body)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body
|
||||
class="container max-w-3xl mx-auto px-4 transition-colors duration-[2s]"
|
||||
>
|
||||
<header class="mt-14 md:mt-24 mb-14">
|
||||
<div class="inline-flex items-center w-full">
|
||||
<h1 class="text-4xl md:text-5xl font-serif font-medium">
|
||||
<a
|
||||
href="/"
|
||||
class="dark:hover:text-muted-dark hover:text-muted-light transition-all duration-500 text-nowrap tracking-wide"
|
||||
><em>The Involution.</em></a
|
||||
>
|
||||
</h1>
|
||||
<div
|
||||
class="w-full flex-grow flex-shrink rounded-lg h-1 bg-muted-light dark:bg-muted-dark mx-4"
|
||||
></div>
|
||||
</div>
|
||||
<p class="mt-8 mb-3 px-1 italic font-light">
|
||||
a web-log about computers and math and hacking.
|
||||
</p>
|
||||
<a class="text-sm text-iris-light dark:text-iris-dark hover:text-love-light dark:hover:text-love-dark" href="https://youwen.dev"
|
||||
><em>by </em>Youwen Wu</a
|
||||
>
|
||||
<span class="ml-2 font-serif">|</span>
|
||||
<button
|
||||
id="theme-toggle"
|
||||
class="ml-2 text-sm hover:text-accent-light dark:hover:text-muted-dark"
|
||||
></button>
|
||||
<span class="ml-2 font-serif">|</span>
|
||||
<button
|
||||
id="font-toggle"
|
||||
class="ml-2 text-sm hover:text-accent-light dark:hover:text-muted-dark"
|
||||
></button>
|
||||
</header>
|
||||
<article>
|
||||
<header>
|
||||
<h1 class="text-4xl">
|
||||
<a href="./nix-automatic-hash-updates-made-easy.html">Nix automatic hash updates made easy</a>
|
||||
</h1>
|
||||
<p
|
||||
class="mb-1 mt-2 italic font-light text-lg text-accent-light dark:text-accent-dark"
|
||||
>
|
||||
keep your flakes up to date
|
||||
</p>
|
||||
<div class="mt-2">2024-12-28</div>
|
||||
<div class="mt-1 text-sm">
|
||||
|
||||
</div>
|
||||
</header>
|
||||
<main class="post mt-4"><p>Nix users often create flakes to package software out of tree, like this <a href="https://github.com/youwen5/zen-browser-flake">Zen
|
||||
Browser flake</a> I’ve been
|
||||
maintaining. Keeping them up to date is a hassle though, since you have to
|
||||
update the Subresource Integrity (SRI) hashes that Nix uses to ensure
|
||||
reproducibility.</p>
|
||||
<p>Here’s a neat method I’ve been using to cleanly handle automatic hash updates.
|
||||
I use <a href="https://www.nushell.sh/">Nushell</a> to easily work with data, prefetch
|
||||
some hashes, and put it all in a JSON file that can be read by Nix at build
|
||||
time.</p>
|
||||
<p>First, let’s create a file called <code>update.nu</code>. At the top, place this shebang:</p>
|
||||
<pre class="nu"><code>#!/usr/bin/env -S nix shell nixpkgs#nushell --command nu</code></pre>
|
||||
<p>This will execute the script in a Nushell environment, which is fetched by Nix.</p>
|
||||
<h2 id="get-the-up-to-date-urls">Get the up to date URLs</h2>
|
||||
<p>We need to obtain the latest version of whatever software we want to update.
|
||||
In this case, I’ll use GitHub releases as my source of truth.</p>
|
||||
<p>You can use the GitHub API to fetch metadata about all the releases of a repository.</p>
|
||||
<pre><code>https://api.github.com/repos/($repo)/releases</code></pre>
|
||||
<p>Roughly speaking, the raw JSON returned by the GitHub releases API looks something like:</p>
|
||||
<pre><code>[
|
||||
{tag_name: "foo", prerelease: false, ...},
|
||||
{tag_name: "bar", prerelease: true, ...},
|
||||
{tag_name: "foobar", prerelease: false, ...},
|
||||
]
|
||||
</code></pre>
|
||||
<p>Note that the ordering of the objects in the array is chronological.</p>
|
||||
<blockquote>
|
||||
<p>Even if you aren’t using GitHub releases, as long as there is a reliable way to
|
||||
programmatically fetch the latest download URLs of whatever software you’re
|
||||
packaging, you can adapt this approach for your specific case.</p>
|
||||
</blockquote>
|
||||
<p>We use Nushell’s <code>http get</code> to make a network request. Nushell will
|
||||
automatically detect and parse the JSON reponse into a Nushell table.</p>
|
||||
<p>In my case, Zen Browser frequently publishes prerelease “twilight” builds which
|
||||
we don’t want to update to. So, we ignore any releases tagged “twilight” or
|
||||
marked “prerelease” by filtering them out with the <code>where</code> selector.</p>
|
||||
<p>Finally, we retrieve the tag name of the item at the first index, which would
|
||||
be the latest release (since the JSON array was chronologically sorted).</p>
|
||||
<pre class="nu"><code>#!/usr/bin/env -S nix shell nixpkgs#nushell --command nu
|
||||
|
||||
# get the latest tag of the latest release that isn't a prerelease
|
||||
def get_latest_release [repo: string] {
|
||||
try {
|
||||
http get $"https://api.github.com/repos/($repo)/releases"
|
||||
| where prerelease == false
|
||||
| where tag_name != "twilight"
|
||||
| get tag_name
|
||||
| get 0
|
||||
} catch { |err| $"Failed to fetch latest release, aborting: ($err.msg)" }
|
||||
}</code></pre>
|
||||
<h2 id="prefetching-sri-hashes">Prefetching SRI hashes</h2>
|
||||
<p>Now that we have the latest tags, we can easily obtain the latest download URLs, which are of the form:</p>
|
||||
<pre><code>https://github.com/zen-browser/desktop/releases/download/$tag/zen.linux-x86_64.tar.bz2
|
||||
https://github.com/zen-browser/desktop/releases/download/$tag/zen.aarch64-x86_64.tar.bz2</code></pre>
|
||||
<p>However, we still need the corresponding SRI hashes to pass to Nix.</p>
|
||||
<div class="sourceCode" id="cb6"><pre class="sourceCode nix"><code class="sourceCode nix"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>src = fetchurl <span class="op">{</span></span>
|
||||
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a> <span class="va">url</span> <span class="op">=</span> <span class="st">"https://github.com/zen-browser/desktop/releases/download/1.0.2-b.5/zen.linux-x86_64.tar.bz2"</span><span class="op">;</span></span>
|
||||
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> <span class="va">hash</span> <span class="op">=</span> <span class="st">"sha256-00000000000000000000000000000000000000000000"</span><span class="op">;</span></span>
|
||||
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
|
||||
<p>The easiest way to obtain these new hashes is to update the URL and then set
|
||||
the hash property to an empty string (<code>""</code>). Nix will spit out an hash mismatch
|
||||
error with the correct hash. However, this is inconvenient for automated
|
||||
command line scripting.</p>
|
||||
<p>The Nix documentation mentions
|
||||
<a href="https://nix.dev/manual/nix/2.18/command-ref/nix-prefetch-url">nix-prefetch-url</a>
|
||||
as a way to obtain these hashes, but as usual, it doesn’t work quite right and
|
||||
has also been replaced by a more powerful but underdocumented experimental
|
||||
feature instead.</p>
|
||||
<p>The <a href="https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix3-store-prefetch-file">nix store
|
||||
prefetch-file</a>
|
||||
command does what <code>nix-prefetch-url</code> is supposed to do, but handles the caveats
|
||||
that lead to the wrong hash being produced automatically.</p>
|
||||
<p>Let’s write a Nushell function that outputs the SRI hash of the given URL. We
|
||||
tell <code>prefetch-file</code> to output structured JSON that we can parse.</p>
|
||||
<p>Since Nushell <em>is</em> a shell, we can directly invoke shell commands like usual,
|
||||
and then process their output with pipes.</p>
|
||||
<pre class="nu"><code>def get_nix_hash [url: string] {
|
||||
nix store prefetch-file --hash-type sha256 --json $url | from json | get hash
|
||||
}</code></pre>
|
||||
<p>Cool! Now <code>get_nix_hash</code> can give us SRI hashes that look like this:</p>
|
||||
<pre><code>sha256-K3zTCLdvg/VYQNsfeohw65Ghk8FAjhOl8hXU6REO4/s=</code></pre>
|
||||
<h2 id="putting-it-all-together">Putting it all together</h2>
|
||||
<p>Now that we’re able to fetch the latest release, obtain the download URLs, and
|
||||
compute their SRI hashes, we have all the information we need to make an
|
||||
automated update. However, these URLs are typically hardcoded in our Nix
|
||||
expressions. The question remains as to how to update these values.</p>
|
||||
<p>A common way I’ve seen updates performed is using something like <code>sed</code> to
|
||||
modify the Nix expressions in place. However, there’s actually a more
|
||||
maintainable and easy to understand approach.</p>
|
||||
<p>Let’s have our Nushell script generate the URLs and hashes and place them in a
|
||||
JSON file! Then, we’ll be able to read the JSON file from Nix and obtain the
|
||||
URL and hash.</p>
|
||||
<pre class="nu"><code>def generate_sources [] {
|
||||
let tag = get_latest_release "zen-browser/desktop"
|
||||
let prev_sources = open ./sources.json
|
||||
|
||||
if $tag == $prev_sources.version {
|
||||
# everything up to date
|
||||
return $tag
|
||||
}
|
||||
|
||||
# generate the download URLs with the new tag
|
||||
let x86_64_url = $"https://github.com/zen-browser/desktop/releases/download/($tag)/zen.linux-x86_64.tar.bz2"
|
||||
let aarch64_url = $"https://github.com/zen-browser/desktop/releases/download/($tag)/zen.linux-aarch64.tar.bz2"
|
||||
|
||||
# create a Nushell record that maps cleanly to JSON
|
||||
let sources = {
|
||||
# add a version field as well for convenience
|
||||
version: $tag
|
||||
|
||||
x86_64-linux: {
|
||||
url: $x86_64_url
|
||||
hash: (get_nix_hash $x86_64_url)
|
||||
}
|
||||
aarch64-linux: {
|
||||
url: $aarch64_url
|
||||
hash: (get_nix_hash $aarch64_url)
|
||||
}
|
||||
}
|
||||
|
||||
echo $sources | save --force "sources.json"
|
||||
|
||||
return $tag
|
||||
}</code></pre>
|
||||
<p>Running this script with</p>
|
||||
<div class="sourceCode" id="cb10"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">chmod</span> +x ./update.nu</span>
|
||||
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="ex">./update.nu</span></span></code></pre></div>
|
||||
<p>gives us the file <code>sources.json</code>:</p>
|
||||
<div class="sourceCode" id="cb11"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
|
||||
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a> <span class="dt">"version"</span><span class="fu">:</span> <span class="st">"1.0.2-b.5"</span><span class="fu">,</span></span>
|
||||
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">"x86_64-linux"</span><span class="fu">:</span> <span class="fu">{</span></span>
|
||||
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">"url"</span><span class="fu">:</span> <span class="st">"https://github.com/zen-browser/desktop/releases/download/1.0.2-b.5/zen.linux-x86_64.tar.bz2"</span><span class="fu">,</span></span>
|
||||
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">"hash"</span><span class="fu">:</span> <span class="st">"sha256-K3zTCLdvg/VYQNsfeohw65Ghk8FAjhOl8hXU6REO4/s="</span></span>
|
||||
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a> <span class="fu">},</span></span>
|
||||
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">"aarch64-linux"</span><span class="fu">:</span> <span class="fu">{</span></span>
|
||||
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a> <span class="dt">"url"</span><span class="fu">:</span> <span class="st">"https://github.com/zen-browser/desktop/releases/download/1.0.2-b.5/zen.linux-aarch64.tar.bz2"</span><span class="fu">,</span></span>
|
||||
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a> <span class="dt">"hash"</span><span class="fu">:</span> <span class="st">"sha256-NwIYylGal2QoWhWKtMhMkAAJQ6iNHfQOBZaxTXgvxAk="</span></span>
|
||||
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a> <span class="fu">}</span></span>
|
||||
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
|
||||
<p>Now, let’s read this from Nix. My file organization looks like the following:</p>
|
||||
<pre><code>./
|
||||
| flake.nix
|
||||
| zen-browser-unwrapped.nix
|
||||
| ...other files...</code></pre>
|
||||
<p><code>zen-browser-unwrapped.nix</code> contains the derivation for Zen Browser. Let’s add
|
||||
<code>version</code>, <code>url</code>, and <code>hash</code> to its inputs:</p>
|
||||
<div class="sourceCode" id="cb13"><pre class="sourceCode nix"><code class="sourceCode nix"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
|
||||
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a> <span class="va">stdenv</span><span class="op">,</span></span>
|
||||
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a> <span class="va">fetchurl</span><span class="op">,</span></span>
|
||||
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a> <span class="co"># add these below</span></span>
|
||||
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a> <span class="va">version</span><span class="op">,</span></span>
|
||||
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a> <span class="va">url</span><span class="op">,</span></span>
|
||||
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a> <span class="va">hash</span><span class="op">,</span></span>
|
||||
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a> <span class="op">...</span></span>
|
||||
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>:</span>
|
||||
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>stdenv.mkDerivation <span class="op">{</span></span>
|
||||
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a> <span class="co"># inherit version from inputs</span></span>
|
||||
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a> <span class="kw">inherit</span> version<span class="op">;</span></span>
|
||||
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a> <span class="va">pname</span> <span class="op">=</span> <span class="st">"zen-browser-unwrapped"</span><span class="op">;</span></span>
|
||||
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a> <span class="va">src</span> <span class="op">=</span> fetchurl <span class="op">{</span></span>
|
||||
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a> <span class="co"># inherit the URL and hash we obtain from the inputs</span></span>
|
||||
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a> <span class="kw">inherit</span> url hash<span class="op">;</span></span>
|
||||
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a> <span class="op">};</span></span>
|
||||
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>Then in <code>flake.nix</code>, let’s provide the derivation with the data from <code>sources.json</code>:</p>
|
||||
<div class="sourceCode" id="cb14"><pre class="sourceCode nix"><code class="sourceCode nix"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span></span>
|
||||
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a> <span class="va">supportedSystems</span> <span class="op">=</span> <span class="op">[</span></span>
|
||||
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a> <span class="st">"x86_64-linux"</span></span>
|
||||
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a> <span class="st">"aarch64-linux"</span></span>
|
||||
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a> <span class="op">];</span></span>
|
||||
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a> <span class="va">forAllSystems</span> <span class="op">=</span> nixpkgs.lib.genAttrs supportedSystems<span class="op">;</span></span>
|
||||
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="kw">in</span></span>
|
||||
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
|
||||
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a> <span class="co"># rest of file omitted for simplicity</span></span>
|
||||
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a> <span class="va">packages</span> <span class="op">=</span> forAllSystems <span class="op">(</span></span>
|
||||
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a> <span class="va">system</span><span class="op">:</span></span>
|
||||
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span></span>
|
||||
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a> <span class="va">pkgs</span> <span class="op">=</span> <span class="bu">import</span> nixpkgs <span class="op">{</span> <span class="kw">inherit</span> system<span class="op">;</span> <span class="op">};</span></span>
|
||||
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a> <span class="co"># parse sources.json into a Nix attrset</span></span>
|
||||
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a> <span class="va">sources</span> <span class="op">=</span> <span class="bu">builtins</span>.fromJSON <span class="op">(</span><span class="bu">builtins</span>.readFile <span class="ss">./sources.json</span><span class="op">);</span></span>
|
||||
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a> <span class="kw">in</span></span>
|
||||
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a> <span class="kw">rec</span> <span class="op">{</span></span>
|
||||
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a> <span class="va">zen-browser-unwrapped</span> <span class="op">=</span> pkgs.callPackage <span class="ss">./zen-browser-unwrapped.nix</span> <span class="op">{</span></span>
|
||||
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a> <span class="kw">inherit</span> <span class="op">(</span>sources.$<span class="op">{</span><span class="va">system</span><span class="op">})</span> hash url<span class="op">;</span></span>
|
||||
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a> <span class="kw">inherit</span> <span class="op">(</span>sources<span class="op">)</span> version<span class="op">;</span></span>
|
||||
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a></span>
|
||||
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a> <span class="co"># if the above is difficult to understand, it is equivalent to the following:</span></span>
|
||||
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a> <span class="va">hash</span> <span class="op">=</span> sources.$<span class="op">{</span><span class="va">system</span><span class="op">}</span>.hash<span class="op">;</span></span>
|
||||
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true" tabindex="-1"></a> <span class="va">url</span> <span class="op">=</span> sources.$<span class="op">{</span><span class="va">system</span><span class="op">}</span>.url<span class="op">;</span></span>
|
||||
<span id="cb14-25"><a href="#cb14-25" aria-hidden="true" tabindex="-1"></a> <span class="va">version</span> <span class="op">=</span> sources.version<span class="op">;</span></span>
|
||||
<span id="cb14-26"><a href="#cb14-26" aria-hidden="true" tabindex="-1"></a> <span class="op">};</span></span>
|
||||
<span id="cb14-27"><a href="#cb14-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
|
||||
<p>Now, running <code>nix build .#zen-browser-unwrapped</code> will be able to use the hashes
|
||||
and URLs from <code>sources.json</code> to build the package!</p>
|
||||
<h2 id="automating-it-in-ci">Automating it in CI</h2>
|
||||
<p>We now have a script that can automatically fetch releases and generate hashes
|
||||
and URLs, as well as a way for Nix to use the outputted JSON to build
|
||||
derivations. All that’s left is to fully automate it using CI!</p>
|
||||
<p>We are going to use GitHub actions for this, as it’s free and easy and you’re
|
||||
probably already hosting on GitHub.</p>
|
||||
<p>Ensure you’ve set up actions for your repo and given it sufficient permissions.</p>
|
||||
<p>We’re gonna run it on a cron timer that checks for updates at 8 PM PST every day.</p>
|
||||
<p>We use DeterminateSystems’ actions to help set up Nix. Then, we simply run our
|
||||
update script. Since we made the script return the tag it fetched, we can store
|
||||
it in a variable and then use it in our commit message.</p>
|
||||
<pre><code>name: Update to latest version, and update flake inputs
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 4 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: Update flake inputs and browser
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check flake inputs
|
||||
uses: DeterminateSystems/flake-checker-action@v4
|
||||
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
|
||||
- name: Set up magic Nix cache
|
||||
uses: DeterminateSystems/magic-nix-cache-action@main
|
||||
|
||||
- name: Check for update and perform update
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
chmod +x ./update.nu
|
||||
export ZEN_LATEST_VER="$(./update.nu)"
|
||||
|
||||
git add -A
|
||||
git commit -m "github-actions: update to $ZEN_LATEST_VER" || echo "Latest version is $ZEN_LATEST_VER, no updates found"
|
||||
|
||||
nix flake update --commit-lock-file
|
||||
|
||||
git push</code></pre>
|
||||
<p>Now, our repository will automatically check for and perform updates every day!</p></main>
|
||||
</article>
|
||||
|
||||
<footer class="mt-14 md:mt-24 pb-12 font-light">
|
||||
<hr
|
||||
class="border-0 dark:bg-muted-dark bg-muted-light rounded-xl h-0.5 mb-4"
|
||||
/>
|
||||
<p class="text-sm leading-relaxed">
|
||||
© 2024 Youwen Wu. Generated by
|
||||
<a
|
||||
href="https://jaspervdj.be/hakyll/"
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
>Hakyll.</a
|
||||
>
|
||||
View the source
|
||||
<a
|
||||
href="https://github.com/couscousdude/blog"
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
>on GitHub.</a
|
||||
>
|
||||
</p>
|
||||
<p class="text-sm leading-relaxed mt-2">
|
||||
Content freely available under
|
||||
<a
|
||||
class="external-link-muted"
|
||||
target="__blank"
|
||||
href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en"
|
||||
><span class="smallcaps">CC BY-NC-SA</span> 4.0</a
|
||||
>
|
||||
unless otherwise noted.
|
||||
</p>
|
||||
</footer>
|
||||
<script defer src="./out/bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
1
out/bundle.css
Normal file
1
out/bundle.css
Normal file
File diff suppressed because one or more lines are too long
1
out/bundle.js
Normal file
1
out/bundle.js
Normal file
|
@ -0,0 +1 @@
|
|||
const e=window.matchMedia("(prefers-color-scheme: dark)").matches,t=()=>{document.documentElement.classList.remove("dark")},s=()=>{document.documentElement.classList.add("dark")};let o="dark"===localStorage.getItem("theme")?2:"light"===localStorage.getItem("theme")?1:0;const a=document.getElementById("theme-toggle");a.addEventListener("click",(()=>{switch(o=(o+1)%3,o){case 0:localStorage.removeItem("theme"),e?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark"),a.innerText="theme: system";break;case 1:e?(localStorage.setItem("theme","light"),t(),a.innerText="theme: light"):(localStorage.setItem("theme","dark"),s(),a.innerText="theme: dark");break;case 2:e?(localStorage.setItem("theme","dark"),s(),a.innerText="theme: dark"):(localStorage.setItem("theme","light"),t(),a.innerText="theme: light")}}));const n=()=>{document.body.classList.remove("font-sans"),document.body.classList.remove("font-serif")},m=e=>{e&&"serif"===e&&(n(),document.body.classList.add("font-serif")),e&&"sans"===e&&(n(),document.body.classList.add("font-sans")),e||n()};let c=localStorage.getItem("font");m();const l=document.getElementById("font-toggle");l.addEventListener("click",(()=>{c=localStorage.getItem("font"),"sans"===c?(c="serif",l.innerText="serif",localStorage.setItem("font","serif")):(c="sans",l.innerText="sans",localStorage.setItem("font","sans")),m(c)}));
|
1101
random-variables-distributions-and-probability-theory.html
Normal file
1101
random-variables-distributions-and-probability-theory.html
Normal file
File diff suppressed because it is too large
Load diff
2
robots.txt
Normal file
2
robots.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
User-agent: *
|
||||
Disallow:
|
37
sitemap.xml
Normal file
37
sitemap.xml
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
|
||||
<url>
|
||||
<loc>https://blog.youwen.dev</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>https://blog.youwen.dev/random-variables-distributions-and-probability-theory.html</loc>
|
||||
<lastmod>2025-02-16</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>https://blog.youwen.dev/an-assortment-of-preliminaries-on-linear-algebra.html</loc>
|
||||
<lastmod>2025-02-15</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>https://blog.youwen.dev/nix-automatic-hash-updates-made-easy.html</loc>
|
||||
<lastmod>2024-12-28</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
|
||||
<url>
|
||||
<loc>https://blog.youwen.dev/a-haskellian-blog.html</loc>
|
||||
<lastmod>2024-05-25T12:00:00Z</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
|
||||
</urlset>
|
Loading…
Reference in a new issue