ToC

Emmy

A powerful computer algebra system written in Clojure(Script).

Emmy logo

The interactive documentation on this page was generated using Clerk. Follow the instructions in the README to run and modify this notebook on your machine!

See the Github project for more details, and the cljdoc page for detailed API documentation.

What is Emmy?

Emmy is a Clojure(Script) implementation of the scmutils system for math and physics investigations in the Clojure and ClojureScript languages. Emmy provides facilities for

And implementations of many different mathematical objects, all built on a tower of generic, extensible mathematical operations.

Scmutils is extensively used in the textbooks The Structure and Interpretation of Classical Mechanics and Functional Differential Geometry by G.J. Sussman and J. Wisdom.

Quickstart

Install Emmy into your Clojurescript project using the instructions at its Clojars page:

Or grab the most recent code using a Git dependency:

{io.github.mentat-collective/emmy
{:git/sha "f807468438482773021d86ab293a89b97338405a"}}

Require emmy.env in your Clojure(Script) namespace:

(ns my-app
(:require [emmy.env :as e :refer :all]))

Guides

These guides are currently woefully incomplete... we need more! Please hold tight while we work on these...

Arithmetic / Numeric Tower

Math works as expected (se Generics for the full menu of operations), but notice that the numeric tower includes complex numbers, and proper ratios in ClojureScript:

(- (* 7 (/ 1 2)) 2)
3/2
(->infix (asin -10))
"
complex(-1.5707963267948966, 2.9932228461263786)"

Symbolic Arithmetic

Symbols are interpreted as abstract complex numbers, and arithmetic on them generates symbolic expressions.

(square (sin (+ 'a 3)))
(expt (sin (+ a 3)) 2)

Render to an infix string with ->infix:

(->infix
(square (sin (+ 'a 3))))
"
sin²(a + 3)"

Or to Loading... with ->TeX:

(clerk/tex
(->TeX
(square (sin (+ 'a 3)))))
Loading...

Note the additional nextjournal.clerk/tex wrapper here, signaling to the notebook that we should render the string returned by ->TeX as Loading....

Let's define a render function that does this for us:

(def render (comp clerk/tex ->TeX))
#object[clojure.core$comp$fn__5876 0x2cf582bb "
clojure.core$comp$fn__5876@2cf582bb"
]

simplify can simplify symbolic expressions:

(let [expr (+ (square (sin 'x))
(square (cos 'x)))]
(render
[expr (simplify expr)]))
Loading...

If you name a symbol after a greek letter, it will render to that letter. Capitalize the first letter to get the capital version of the character:

(render
(+ 'Theta 'alpha))
Loading...

Special suffixes like dot, dotdot, prime, primeprime, var, vec and tilde will modify the symbol's infix or Loading... representation. _ triggers a subscript, and the unicode character ↑ will trigger a superscript.

Here's a selection of examples:

(render
(up
'alphadot_beta
'xdotdot
'zetaprime_alphadot
'alphaprimeprime_mubar
'vbar
'Pivec
'alphatilde))
Loading...

Automatic Differentiation

Use the D operator to perform forward-mode automatic differentiation.

(render
((D cube) 'x))
Loading...

Generate the Taylor series expansion of a literal function f by exponentiating the D operator:

(let [f (literal-function 'f)]
(render
(simplify
(series:sum (((exp D) f) 'x) 5))))
Loading...

Physics, Classical Mechanics

SICMUtils is based on the engine behind Sussman and Wisdom's The Structure and Interpretation of Classical Mechanics, and has a built-in API for exploring Lagrangian and Hamiltonian mechanics.

Define a Lagrangian for a central potential U acting on a particle with mass m:

(defn L-central-polar [m U]
(fn [[_ [r] [rdot thetadot]]]
(- (* 1/2 m
(+ (square rdot)
(square (* r thetadot))))
(U r))))
#object[emmy.notebook$L_central_polar 0xaec92e3 "
emmy.notebook$L_central_polar@aec92e3"
]

and generate the two Euler-Lagrange equations of motion for the r and theta coordinates:

(let [potential-fn (literal-function 'U)
L (L-central-polar 'm potential-fn)
state (up (literal-function 'r)
(literal-function 'theta))]
(render
(simplify
(((Lagrange-equations L) state) 't))))
Loading...

Emmy via SCI

Emmy is compatible with SCI, the Small Clojure Interpreter.

To install Emmy into your SCI context, require the emmy.sci namespace and call emmy.sci/install!:

(ns myproject.sci-extensions
(:require [emmy.sci]))
(emmy.sci/install!)

If you want more granular control, see the cljdoc page for emmy.sci for an SCI config and distinct SCI namespace objects that you can piece together.

Note that Emmy does not ship with a dependency on SCI, so you'll need to install your own version.

Emmy via Clerk

Using Emmy with Nextjournal's Clerk gives you the ability to write notebooks like this one.

Doing this requires that you generate a custom ClojureScript build for your Clerk project. The easiest way to do this for an existing project is with the clerk-utils project. Follow the instructions on the clerk-utils guide for custom ClojureScript.

If this is your first time using Clerk, use the emmy/clerk template described below to generate a new project with all steps described in "Emmy via SCI" already completed.

Project Template

Emmy includes a deps-new template called emmy/clerk that makes it easy to configure a new Clerk project with everything described in "Emmy via SCI" already configured.

First, install the deps-new tool:

clojure -Ttools install io.github.seancorfield/deps-new '{:git/tag "v0.5.0"}' :as new

To create a new Clerk project based on emmy/clerk in a folder called my-notebook-project, run the following command:

clojure -Sdeps '{:deps {io.github.mentat-collective/emmy {:git/sha "f807468438482773021d86ab293a89b97338405a"}}}' \
-Tnew create \
:template emmy/clerk \
:name myusername/my-notebook-project

The README.md file in the generated project contains information on how to develop within the new project.

If you have an existing Clerk notebook project and are considering adding Emmy, you might consider using emmy/clerk to get some ideas on how to structure your own project.

clj-kondo config

Emmy ships with a configuration that allows clj-kondo to lint the library's macros.

To install the exported linter configuration:

  1. Install clj-kondo using these instructions. I highly recommend configuring editor integration for your text editor.

  2. If it doesn't exist yet, create a .clj-kondo folder in your project:

mkdir .clj-kondo
  1. Run clj-kondo using the following command. This will import the emmy config and populate clj-kondo's cache with linting information about all of your dependencies:
# If you're using Leiningen:
clj-kondo --copy-configs --dependencies --lint$(lein classpath)"
# If you're using deps.edn:
clj-kondo --copy-configs --dependencies --lint "$(clojure -Spath)"

The steps listed here mirror the instructions in the clj-kondo repo.

Explore the Project

Many of the namespaces in the project are written up as literate essays. Expect more organization here in coming versions; for now, here is the full list of namespace essays.

Who is using Emmy?

The following projects use Emmy:

If you want to show off your use of Emmy, please file a ticket and let us know!

Thanks and Support

To support this work and my other open source projects, consider sponsoring me via my GitHub Sponsors page. Thank you to my current sponsors!

For more information on me and my work, visit https://samritchie.io.

License

Copyright © 2022-2023 Sam Ritchie and Colin Smith.

Distributed under the GPLv3 License. See LICENSE.