SICMUtils/Emmy - Clojure library for symbolic mathematics, automatic differentiation, and classical mechanics. Bridges SICM concepts to executable computation via SRFI-compatible abstractions.
/plugin marketplace add plurigrid/asi/plugin install asi-skills@asi-skillsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
"Executable mathematics for computational physics" — Sam Ritchie (mentat-collective)
SICMUtils (now Emmy) is the Clojure implementation of the scmutils library from SICM. It provides:
┌─────────────────────────────────────────────────────────────┐
│ BEFORE SRFI BRIDGE │
├─────────────────────────────────────────────────────────────┤
│ SICMUtils (Clojure) SRFI (Scheme) │
│ ═══════════════════ ═════════════ │
│ emmy.generic/* SRFI-1 (lists) ╳ ISOLATED │
│ emmy.structure/* SRFI-9 (records) ╳ ISOLATED │
│ emmy.expression/* SRFI-27 (random) ╳ ISOLATED │
│ emmy.calculus/* SRFI-45 (lazy) ╳ ISOLATED │
│ emmy.mechanics/* SRFI-171 (transducers) ╳ │
│ │
│ No compositional path: Clojure ↛ Scheme │
│ No GF(3) conservation across language boundary │
│ No splittable RNG interop │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ AFTER SRFI BRIDGE (via Cat# bicomodules) │
├─────────────────────────────────────────────────────────────┤
│ SICMUtils (Clojure) SRFI (Scheme) │
│ ═══════════════════ ═════════════ │
│ │
│ emmy.generic/* ────────────► SRFI-1 (fold/unfold) │
│ │ Bicomodule: List transformations │
│ │ ListAlgebra preserve structure │
│ ▼ │
│ emmy.structure/* ──────────► SRFI-9 (define-record-type) │
│ │ Bicomodule: Up/down tuples ↔ records │
│ │ StructBridge │
│ ▼ │
│ emmy.expression/* ─────────► SRFI-27 (random-source) │
│ │ Bicomodule: SplitMix64 ↔ random-source │
│ │ RNGBridge preserves determinism │
│ ▼ │
│ emmy.calculus/* ───────────► SRFI-45 (delay/force) │
│ │ Bicomodule: Lazy derivatives ↔ promises │
│ │ LazyDiff │
│ ▼ │
│ emmy.mechanics/* ──────────► SRFI-171 (transducers) │
│ Bicomodule: Phase space evolution as │
│ PhaseXduce composable transformation │
│ │
│ GF(3) CONSERVED across boundary via Gay.jl coloring │
└─────────────────────────────────────────────────────────────┘
| SICMUtils Module | SRFI | Bicomodule | Trit | Reachable |
|---|---|---|---|---|
emmy.generic | 1 | ListAlgebra | -1 | ✓ AFTER |
emmy.structure | 9 | StructBridge | -1 | ✓ AFTER |
emmy.expression | 27 | RNGBridge | 0 | ✓ AFTER |
emmy.calculus | 45 | LazyDiff | 0 | ✓ AFTER |
emmy.numerical.ode | 171 | PhaseXduce | +1 | ✓ AFTER |
emmy.mechanics.lagrange | 204 | PatternMech | +1 | ✓ AFTER |
;; Clojure side (SICMUtils)
(ns sicmutils.srfi-bridge.list-algebra
(:require [emmy.generic :as g]))
(defn fold-to-srfi
"Translate emmy fold to SRFI-1 fold signature."
[f init coll]
;; SRFI-1: (fold kons knil list)
;; Emmy: (reduce f init coll)
(reduce f init coll))
(defn unfold-from-srfi
"Generate sequence using SRFI-1 unfold semantics."
[p f g seed]
;; SRFI-1: (unfold p f g seed)
(take-while (complement p)
(iterate g (f seed))))
;; Scheme side (SRFI-1)
(import (srfi 1))
(define (emmy-compatible-fold kons knil lis)
;; Wrap to ensure Clojure-compatible left fold
(fold kons knil lis))
;; Bridge Gay.jl SplitMix64 to SRFI-27 random-source
(ns sicmutils.srfi-bridge.rng
(:require [emmy.expression :as expr]))
(def ^:const GOLDEN 0x9e3779b97f4a7c15)
(def ^:const MIX1 0xbf58476d1ce4e5b9)
(def ^:const MIX2 0x94d049bb133111eb)
(defn splitmix64 [x]
(let [x (unchecked-add x GOLDEN)
x (unchecked-multiply (bit-xor x (unsigned-bit-shift-right x 30)) MIX1)
x (unchecked-multiply (bit-xor x (unsigned-bit-shift-right x 27)) MIX2)]
(bit-xor x (unsigned-bit-shift-right x 31))))
(defn make-emmy-random-source [seed]
{:seed (atom seed)
:next-int (fn []
(let [current @(:seed this)
next (splitmix64 current)]
(reset! (:seed this) next)
next))})
;; SRFI-27 wrapper for Emmy RNG
(import (srfi 27))
(define (make-emmy-compatible-source seed)
(let ((source (make-random-source)))
(random-source-pseudo-randomize! source seed 1069)
source))
;; Verify determinism matches Gay.jl
(define (verify-splitmix seed expected)
(let* ((source (make-emmy-compatible-source seed))
(rand-int (random-source-make-integers source)))
(= (rand-int (expt 2 64)) expected)))
;; Lazy derivative computation
(ns sicmutils.srfi-bridge.lazy-diff
(:require [emmy.calculus.derivative :as d]))
(defn lazy-D
"Delay derivative computation until forced."
[f]
(delay (d/D f)))
(defn force-derivative [lazy-df x]
(@lazy-df x))
;; SRFI-45 lazy derivatives
(import (srfi 45))
(define (lazy-derivative f)
(delay (lambda (x)
(/ (- (f (+ x 0.0001)) (f x)) 0.0001))))
(define (force-at lazy-df x)
((force lazy-df) x))
;; Phase space evolution as transducer
(ns sicmutils.srfi-bridge.phase-xduce
(:require [emmy.mechanics.hamilton :as ham]))
(defn hamilton-transducer
"Transducer for Hamiltonian evolution."
[H dt]
(fn [rf]
(fn
([] (rf))
([result] (rf result))
([result state]
(rf result (ham/evolve H state dt))))))
;; SRFI-171 transducer for phase evolution
(import (srfi 171))
(define (hamiltonian-xform H dt)
(tmap (lambda (state)
(phase-evolve H state dt))))
;; Compose with other transformations
(define phase-pipeline
(compose
(hamiltonian-xform H 0.01)
(tfilter (lambda (s) (< (energy s) max-energy)))
(ttake 1000)))
Clojure (SICMUtils) Scheme (SRFI)
═══════════════════ ════════════
emmy.generic [-1] ◄─────► SRFI-1 [-1]
emmy.structure [-1] ◄─────► SRFI-9 [-1]
emmy.expression [ 0] ◄─────► SRFI-27 [ 0]
emmy.calculus [ 0] ◄─────► SRFI-45 [ 0]
emmy.mechanics [+1] ◄─────► SRFI-171 [+1]
Σ Clojure = -1 + -1 + 0 + 0 + 1 = -1
Σ Scheme = -1 + -1 + 0 + 0 + 1 = -1
Bicomodule preserves: Σ_source ≡ Σ_target (mod 3) ✓
┌─────────────────────────────────────────────────────────────┐
│ Cat# = Comod(P) for SICM ↔ SRFI │
├─────────────────────────────────────────────────────────────┤
│ Vertical (Functors): │
│ SICMUtils.Mechanics ────► SRFI.Numeric │
│ SICMUtils.Calculus ────► SRFI.Lazy │
│ │
│ Horizontal (Bicomodules): │
│ ListAlgebra: generic ↛ srfi-1 │
│ RNGBridge: expression ↛ srfi-27 │
│ LazyDiff: calculus ↛ srfi-45 │
│ PhaseXduce: mechanics ↛ srfi-171 │
│ │
│ Equipment: │
│ Companions: SICMUtils modules → SRFI libraries │
│ Conjoints: SRFI libraries → SICMUtils modules │
│ Mates: Natural transformations between functors │
└─────────────────────────────────────────────────────────────┘
# Run SICMUtils REPL
clj -M:emmy
# Execute Lagrangian example
clj -X emmy.examples/harmonic-oscillator
# Bridge to Scheme
clj -X sicmutils.srfi-bridge/export-to-scheme :format :srfi-171
# Verify SRFI compatibility
clj -M:test -n sicmutils.srfi-bridge-test
# Check GF(3) conservation
bb verify_trit_balance.bb sicmutils srfi
| sicm Chapter | SICMUtils Namespace | SRFI Bridge |
|---|---|---|
| Ch1 Lagrangian | emmy.mechanics.lagrange | SRFI-171 (transducers) |
| Ch2 Rigid Bodies | emmy.mechanics.rotation | SRFI-9 (records) |
| Ch3 Hamiltonian | emmy.mechanics.hamilton | SRFI-171 (transducers) |
| Ch4 Phase Space | emmy.numerical.ode | SRFI-27 (random) |
| Ch5 Canonical | emmy.calculus.form-field | SRFI-45 (lazy) |
| Ch6 Evolution | emmy.calculus.derivative | SRFI-45 (lazy) |
| Ch7 Perturbation | emmy.series | SRFI-41 (streams) |
| App A Scheme | N/A (native Scheme) | All SRFIs |
Trit: +1 (PLUS - constructive computation)
Home: Physics/Computation
Poly Op: ◁ (substitution for symbolic manipulation)
Kan Role: Lan (extend computation to new domains)
Color: #FF6B35 (energy orange, matches sicm)
sicm (-1) ⊗ sicmutils (0) ⊗ srfi (+1) = 0 ✓
sicp (-1) ⊗ sicmutils (0) ⊗ emmy (+1) = 0 ✓
calculus (-1) ⊗ sicmutils (0) ⊗ physics (+1) = 0 ✓