Skip to content

Commit f52e2bf

Browse files
Merge pull request #164 from kloimhardt/emmy-sicm-ch01
Emmy, the Algebra System: Classical Mechanics Prologue
2 parents 98127eb + 8b29d69 commit f52e2bf

File tree

3 files changed

+355
-0
lines changed

3 files changed

+355
-0
lines changed
Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
^{:kindly/hide-code true
2+
:clay {:title "Emmy, the Algebra System: Classical Mechanics Prologue"
3+
:quarto {:author :kloimhardt
4+
:type :post
5+
:date "2025-11-12"
6+
:image "fdg_prologue.png"
7+
:category :libs
8+
:tags [:emmy :physics]}}}
9+
(ns mentat-collective.emmy.fdg-prologue
10+
(:require [scicloj.kindly.v4.api :as kindly]
11+
[scicloj.kindly.v4.kind :as kind]
12+
[emmy.env :as e :refer [->infix simplify Lagrange-equations literal-function]]
13+
[emmy.mechanics.lagrange :as lg]
14+
[civitas.repl :as repl]))
15+
16+
;; Elemetary introduction to Emmy, taken from the first pages of the open-access book
17+
;; [Functional Differential Geometry (FDG)](https://mitpress.mit.edu/9780262019347/functional-differential-geometry/).
18+
;; The code snippets are executable, copy-paste them to the sidebar of the page.
19+
20+
;; The [Emmy](https://emmy.mentat.org) maintainer, [Sam Ritchie](https://roadtoreality.substack.com/), wrote the source for this page, namely the
21+
;; [LaTex version of FDG](https://github.com/mentat-collective/fdg-book/blob/main/scheme/org/prologue.org).
22+
23+
;; In adopting MIT-Scheme's `(define ...)`, I trust that Clojure people will bridge that gap quickly
24+
;; while being sure of the gratitude of all readers of the immutable, dense book. So without further ado ...
25+
26+
^:kindly/hide-code
27+
(kind/hiccup
28+
[:div
29+
[:script {:src "https://cdn.jsdelivr.net/npm/scittle-kitchen/dist/scittle.js"}]
30+
[:script {:src "https://cdn.jsdelivr.net/npm/scittle-kitchen/dist/scittle.emmy.js"}]
31+
[:script {:src "https://cdn.jsdelivr.net/npm/scittle-kitchen/dist/scittle.cljs-ajax.js"}]
32+
[:script {:src "https://cdn.jsdelivr.net/npm/react@18/umd/react.production.min.js", :crossorigin ""}]
33+
[:script {:src "https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.production.min.js", :crossorigin ""}]
34+
[:script {:src "https://cdn.jsdelivr.net/npm/scittle-kitchen/dist/scittle.reagent.js"}]
35+
[:script {:type "application/x-scittle" :src "scheme.cljc"}]])
36+
37+
^:kindly/hide-code
38+
(kind/scittle
39+
'(require '[emmy.env :refer :all :exclude [Lagrange-equations Gamma]]))
40+
41+
^:kindly/hide-code
42+
(kind/scittle
43+
'(def show-expression (comp ->infix simplify)))
44+
45+
^:kindly/hide-code
46+
(defmacro define [& b]
47+
(list 'kind/scittle (list 'quote (cons 'define b))))
48+
49+
^:kindly/hide-code
50+
(defmacro show-expression [& b]
51+
(list 'kind/reagent [:h3 (list 'quote (cons 'show-expression b))]))
52+
53+
^:kindly/hide-code
54+
(def md
55+
(comp kindly/hide-code kind/md))
56+
57+
;; ## Programming and Understanding
58+
59+
;; One way to become aware of the precision required to unambiguously communicate a
60+
;; mathematical idea is to program it for a computer. Rather than using canned
61+
;; programs purely as an aid to visualization or numerical computation, we use
62+
;; computer programming in a functional style to encourage clear thinking.
63+
;; Programming forces us to be precise and unambiguous, without forcing us to be
64+
;; excessively rigorous. The computer does not tolerate vague descriptions or
65+
;; incomplete constructions. Thus the act of programming makes us keenly aware of
66+
;; our errors of reasoning or unsupported conclusions.[fn:1]
67+
68+
;; Although this book is about differential geometry, we can show how thinking
69+
;; about programming can help in understanding in a more elementary context. The
70+
;; traditional use of Leibniz’s notation and Newton’s notation is convenient in
71+
;; simple situations, but in more complicated situations it can be a serious
72+
;; handicap to clear reasoning.
73+
74+
;; A mechanical system is described by a Lagrangian function of the system state
75+
;; (time, coordinates, and velocities). A motion of the system is described by a
76+
;; path that gives the coordinates for each moment of time. A path is allowed if
77+
;; and only if it satisfies the Lagrange equations. Traditionally, the Lagrange
78+
;; equations are written
79+
80+
;; $$
81+
;;{\frac{d}{dt}\frac{\partial L}{\partial \dot{q}}} -
82+
;; \frac{\partial L}{\partial q}=0.
83+
;; $$
84+
85+
;; What could this expression possibly mean?
86+
87+
;;Let’s try to write a program that implements Lagrange equations. What are
88+
;;Lagrange equations for? Our program must take a proposed path and give a result
89+
;;that allows us to decide if the path is allowed. This is already a problem; the
90+
;;equation shown above does not have a slot for a path to be tested.
91+
92+
;; So we have to figure out how to insert the path to be tested. The partial
93+
;; derivatives do not depend on the path; they are derivatives of the Lagrangian
94+
;; function and thus they are functions with the same arguments as the Lagrangian.
95+
;; But the time derivative $d/dt$ makes sense only for a function of time. Thus we
96+
;; must be intending to substitute the path (a function of time) and its derivative
97+
;; (also a function of time) into the coordinate and velocity arguments of the
98+
;; partial derivative functions.
99+
100+
;; So probably we meant something like the following (assume that $\omega$ is a
101+
;; path through the coordinate configuration space, and so $w(t)$ specifies the
102+
;; configuration coordinates at time $t$):
103+
104+
;; $$\frac{d}{d t}\left( \left.\frac{\partial L(t, q, \dot{q})}{\partial \dot{q}}
105+
;; \right|_{\substack{ {q=w(t)} \\ {\dot{q}=\frac{d w(t)}{d t}} }}
106+
;; \right)-\left.\frac{\partial L(t, q, \dot{q})}{\partial q}\right|_{ \substack{
107+
;; q=w(t) \\ {\dot{q}=\frac{d w(t)}{d t}}} }=0.$$
108+
109+
;; In this equation we see that the partial derivatives of the Lagrangian function
110+
;; are taken, then the path and its derivative are substituted for the position and
111+
;; velocity arguments of the Lagrangian, resulting in an expression in terms of the
112+
;; time.
113+
114+
;; This equation is complete. It has meaning independent of the context and there
115+
;; is nothing left to the imagination. The earlier equations require the reader to
116+
;; fill in lots of detail that is implicit in the context. They do not have a clear
117+
;; meaning independent of the context.
118+
119+
;; By thinking computationally we have reformulated the Lagrange equations into a
120+
;; form that is explicit enough to specify a computation. We could convert it into
121+
;; a program for any symbolic manipulation program because it tells us *how* to
122+
;; manipulate expressions to compute the residuals of Lagrange’s equations for a
123+
;; purported solution path.[fn:2]
124+
125+
;; ## Functional Abstraction
126+
127+
;; But this corrected use of Leibniz notation is ugly. We had to introduce
128+
;; extraneous symbols ($q$ and $\dot{q}$) in order to indicate the argument
129+
;; position specifying the partial derivative. Nothing would change here if we
130+
;; replaced $q$ and $\dot{q}$ by $a$ and $b$.[fn:3] We can simplify the notation by
131+
;; admitting that the partial derivatives of the Lagrangian are themselves new
132+
;; functions, and by specifying the particular partial derivative by the position
133+
;; of the argument that is varied
134+
135+
;; $$\frac{d}{d t}\left(\left(\partial_{2} L\right)\left(t, w(t), \frac{d}{d t}
136+
;; w(t)\right)\right)-\left(\partial_{1} L\right)\left(t, w(t), \frac{d}{d t}
137+
;; w(t)\right)=0,$$
138+
139+
;; where $\partial_{i}L$ is the function which is the partial derivative of the
140+
;; function $L$ with respect to the ith argument.[fn:4]
141+
142+
;; Two different notions of derivative appear in this expression. The functions
143+
;; $\partial_2 L$ $\partial_1 L$, constructed from the Lagrangian $L$, have the
144+
;; same arguments as $L$.
145+
;; The derivative $d/dt$ is an expression derivative. It applies to an expression
146+
;; that involves the variable $t$ and it gives the rate of change of the value of
147+
;; the expression as the value of the variable $t$ is varied.
148+
149+
;; These are both useful interpretations of the idea of a derivative. But functions
150+
;; give us more power. There are many equivalent ways to write expressions that
151+
;; compute the same value. For example $1/(1/r_1 + 1/r_2)=(r_1r_2)/(r_1 + r_2)$.
152+
;; These expressions compute the same function of the two variables $r_1$ and
153+
;; $r_2$. The first expression fails if $r_1 = 0$ but the second one gives the
154+
;; right value of the function. If we abstract the function, say as $\Pi(r_1,
155+
;; r_2)$, we can ignore the details of how it is computed. The ideas become clearer
156+
;; because they do not depend on the detailed shape of the expressions.
157+
158+
;; So let’s get rid of the expression derivative $d/dt$ and replace it with an
159+
;; appropriate functional derivative. If $f$ is a function then we will write $Df$
160+
;; as the new function that is the derivative of $f$:[fn:5]
161+
162+
;; $$(D f)(t)=\left.\frac{d}{d x} f(x)\right|_{x=t}.$$
163+
164+
;; To do this for the Lagrange equation we need to construct a function to take the
165+
;; derivative of.
166+
167+
;; Given a configuration-space path $w$, there is a standard way to make the
168+
;; state-space path. We can abstract this method as a mathematical function
169+
;; $\Gamma$:
170+
171+
;; $$\Gamma[w](t)=\left(t, w(t), \frac{d}{d t} w(t)\right).$$
172+
173+
;; Using $\Gamma$ we can write:
174+
175+
;; $$\frac{d}{dt}\left(\left(\partial_{2} L\right) \left(\Gamma[w](t)\right)
176+
;; \right) - \left(\partial_{1} L\right) \left(\Gamma[w](t)\right)=0.$$
177+
178+
;; If we now define composition of functions $(f \circ g)(x) = f(g(x))$, we can
179+
;; express the Lagrange equations entirely in terms of functions:
180+
181+
;; $$D\left(\left(\partial_{2} L\right) \circ \left(\Gamma[w]\right)\right)
182+
;; -\left(\partial_{1} L\right) \circ \left(\Gamma[w]\right)=0.$$
183+
184+
;; The functions $\partial_1 L$ and $\partial_2 L$ are partial derivatives of the
185+
;; function $L$. Composition with $\Gamma[w]$ evaluates these partials with
186+
;; coordinates and velocites appropriate for the path $w$, making functions of
187+
;; time. Applying $D$ takes the time derivative. The Lagrange equation states that
188+
;; the difference of the resulting functions of time must be zero. This statement
189+
;; of the Lagrange equation is complete, unambiguous, and functional. It is not
190+
;; encumbered with the particular choices made in expressing the Lagrangian. For
191+
;; example, it doesn’t matter if the time is named $t$ or $\tau$, and it has an
192+
;; explicit place for the path to be tested.
193+
194+
;; This expression is equivalent to a computer program:[fn:6]
195+
196+
^:kindly/hide-code
197+
(kind/scittle '(declare Gamma))
198+
199+
(define ((Lagrange-equations Lagrangian) w)
200+
(- (D (compose ((partial 2) Lagrangian) (Gamma w)))
201+
(compose ((partial 1) Lagrangian) (Gamma w))))
202+
203+
;; In the Lagrange equations procedure the parameter `Lagrangian` is a procedure
204+
;; that implements the Lagrangian. The derivatives of the Lagrangian, for example
205+
;; `((partial 2) Lagrangian)`, are also procedures. The state-space path procedure
206+
;; `(Gamma w)` is constructed from the configuration-space path procedure `w` by
207+
;; the procedure `Gamma`:
208+
209+
(define ((Gamma w) t)
210+
(up t (w t) ((D w) t)))
211+
212+
;; where `up` is a constructor for a data structure that represents a state of the
213+
;; dynamical system (time, coordinates, velocities).
214+
215+
;; The result of applying the `Lagrange-equations` procedure to a procedure
216+
;; `Lagrangian` that implements a Lagrangian function is a procedure that takes a
217+
;; configuration-space path procedure `w` and returns a procedure that gives the
218+
;; residual of the Lagrange equations for that path at a time.
219+
220+
;; For example, consider the harmonic oscillator, with Lagrangian
221+
222+
;; $$L(t, q, v) = \frac{1}{2}mv^2 - \frac{1}{2}kq^2,$$
223+
224+
;; for mass $m$ and spring constant $k$. this lagrangian is implemented by
225+
226+
(define ((L-harmonic m k) local)
227+
(let ((q (coordinate local))
228+
(v (velocity local)))
229+
(- (* 1/2 m (square v))
230+
(* 1/2 k (square q)))))
231+
232+
;; We know that the motion of a harmonic oscillator is a sinusoid with a given
233+
;; amplitude $a$, frequency $\omega$, and phase $\varphi$:
234+
235+
;; $$x(t) = a \cos(\omega t + \varphi).$$
236+
237+
;; Suppose we have forgotten how the constants in the solution relate to the
238+
;; physical parameters of the oscillator. Let’s plug in the proposed solution and
239+
;; look at the residual:
240+
241+
(define (proposed-solution t)
242+
(* 'a (cos (+ (* 'omega t) 'phi))))
243+
244+
(show-expression
245+
(((Lagrange-equations (L-harmonic 'm 'k))
246+
proposed-solution)
247+
't))
248+
249+
;; [note by MAK: copy-paste the `(show-expression ...)` code-snippet into the sidebar, press Ctrl+Enter and verify the above result.]
250+
251+
;; The residual here shows that for nonzero amplitude, the only solutions allowed
252+
;; are ones where $(k - m\omega^2) = 0$ or $\omega = \sqrt{k/m}$.
253+
254+
;; But, suppose we had no idea what the solution looks like. We could propose a
255+
;; literal function for the path:
256+
257+
;; [note by MAK: the following does not work in the sidebar because I could not get
258+
;; `literal-function` to work.
259+
;; As a remedy, I have an [alternative execution environment](https://kloimhardt.github.io/blog/html/sicmutils-as-js-book-part1.html) ]
260+
261+
(->infix
262+
(simplify
263+
(((Lagrange-equations (lg/L-harmonic 'm 'k))
264+
(literal-function 'x))
265+
't)))
266+
267+
;; If this residual is zero we have the Lagrange equation for the harmonic
268+
;; oscillator.
269+
270+
;; Note that we can flexibly manipulate representations of mathematical functions.
271+
;; (See Appendices A and B.)
272+
273+
;; We started out thinking that the original statement of Lagrange’s equations
274+
;; accurately captured the idea. But we really don’t know until we try to teach it
275+
;; to a naive student. If the student is sufficiently ignorant, but is willing to
276+
;; ask questions, we are led to clarify the equations in the way that we did. There
277+
;; is no dumber but more insistent student than a computer. A computer will
278+
;; absolutely refuse to accept a partial statement, with missing parameters or a
279+
;; type error. In fact, the original statement of Lagrange’s equations contained an
280+
;; obvious type error: the Lagrangian is a function of multiple variables, but the
281+
;; $d/dt$ is applicable only to functions of one variable.
282+
283+
;; ## Footnotes
284+
285+
;; [fn:6] The programs in this book are written in Scheme, a dialect of Lisp. The
286+
;; details of the language are not germane to the points being made. What is
287+
;; important is that it is mechanically interpretable, and thus unambiguous. In
288+
;; this book we require that the mathematical expressions be explicit enough that
289+
;; they can be expressed as computer programs. Scheme is chosen because it is easy
290+
;; to write programs that manipulate representations of mathematical functions. An
291+
;; informal description of Scheme can be found in Appendix A. The use of Scheme to
292+
;; represent mathematical objects can be found in Appendix B. A formal description
293+
;; of Scheme can be obtained in [10]. You can get the software from [21].
294+
295+
;; [fn:5] An explanation of functional derivatives is in Appendix B, page 202.
296+
297+
;; [fn:4] The argument positions of the Lagrangian are indicated by indices
298+
;; starting with zero for the time argument.
299+
300+
;; [fn:3] That the symbols $q$ and $\dot{q}$ can be replaced by other arbitrarily
301+
;; chosen nonconflicting symbols without changing the meaning of the expression
302+
;; tells us that the partial derivative symbol is a logical quantifier, like forall
303+
;; and exists ($\forall$ and $\exists$).
304+
305+
;; [fn:2] The /residuals/ of equations are the expressions whose value must be zero
306+
;; if the equations are satisfied. For example, if we know that for an unknown $x$,
307+
;; $x^3-x=0$ then the residual is $x^3 - x$. We can try $x = -1$ and find a
308+
;; residual of 0, indicating that our purported solution satisfies the equation. A
309+
;; residual may provide information. For example, if we have the differential
310+
;; equation $df(x)/dx - af(x) = 0$ and we plug in a test solution $f(x) = Ae^{bx}$
311+
;; we obtain the residual $(b - a)Ae^{bx}$, which can be zero only if $b = a$.
312+
313+
;; [fn:1] The idea of using computer programming to develop skills of clear
314+
;; thinking was originally advocated by Seymour Papert. An extensive discussion of
315+
;; this idea, applied to the education of young children, can be found in Papert
316+
;; [13].
317+
318+
(repl/scittle-sidebar)
25 KB
Loading
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
(ns mentat-collective.emmy.scheme)
2+
3+
(defn walk [inner outer form]
4+
(cond
5+
(list? form) (outer (apply list (map inner form)))
6+
(seq? form) (outer (doall (map inner form)))
7+
(coll? form) (outer (into (empty form) (map inner form)))
8+
:else (outer form)))
9+
10+
(defn postwalk [f form]
11+
(walk (partial postwalk f) f form))
12+
13+
(defn postwalk-replace [smap form]
14+
(postwalk (fn [x] (if (contains? smap x) (smap x) x)) form))
15+
16+
(defmacro let-scheme [b & e]
17+
(concat (list 'let (into [] (apply concat b))) e))
18+
19+
(defmacro define-1 [h & b]
20+
(let [body (postwalk-replace {'let 'let-scheme} b)]
21+
(if (coll? h)
22+
(if (coll? (first h))
23+
(list 'defn (ffirst h) (into [] (rest (first h)))
24+
(concat (list 'fn (into [] (rest h))) body))
25+
(concat (list 'defn (first h) (into [] (rest h)))
26+
body))
27+
(concat (list 'def h) body))))
28+
29+
(defmacro define [h & b]
30+
(if (and (coll? h) (= (first h) 'tex-inspect))
31+
(list 'do
32+
(concat ['define-1 (second h)] b)
33+
h)
34+
(concat ['define-1 h] b)))
35+
36+
(defmacro lambda [h b]
37+
(list 'fn (into [] h) b))

0 commit comments

Comments
 (0)