Computer Algebra, Physics and Differential Geometry in Clojure.
This release adds a number of performance upgrades, and completes the port of all code in the mechanics
package of the original scmutils
library.
This will also be the final release before extracting most of the code in the library out and giving it a new identity and home as the "Emmy Computer Algebra System", housed at https://github.com/mentat-collective/emmy.
#531:
Adds proper self-require forms to all cljc
namespaces with macros; this removes the need for :include-macros true
or :refer-macros
and makes the life of consumers simpler.
Upgrades sci, test.check, core.match, timbre, clojurescript, shadow-cljs dependencies to remove various warnings.
Adds sicmutils.structure/symbol-set
Adds IHash
implementations for js/BigInt
, goog.math.Long
, goog.map.Integer
and Ratio
types
#514:
Modifies sicmutils.calculus.derivative/taylor-series
to return a proper PowerSeries
instance, which the user can call with some dx
to get back the old behavior.
The new version can take any number of arguments in addition to f
.
Supplying no arguments returns the expansion at 0; if you supply many
arguments (totally fine!), you'll need to wrap your dx
components in a
vector before supplying them to the returned PowerSeries
.
sicmutils.series/function->
works the same way now, and functions identically, but with a different implementation. (previously it took a single expansion point under a keyword argument :x0
.)
The new sicmutils.calculus.derivative/symbolic-taylor-series
is a port of Taylor-series-coefficients
from scmutils
. It has the same contract as taylor-series
, except that the full expansion is performed symbolically, and the original arguments are substituted in after expansion and simplification.
Other changes:
Installs 1
as the one-like
and identity-like
return values for structures and vectors. A true identity element would be an identity element compatible with all entries of the structure; but as defined now, 1
is a fine choice and matches the scmutils
implementation.
new sicmutils.differential/map-coefficients
, which makes simplify
slightly more efficient by filtering terms .
more efficient sicmutils.expression/variables-in
, maybe 30% faster for big expressions; this makes a difference in the simplifier!
sicmutils.expression/substitute
now works for proper Literal
instances. Before it only worked for unwrapped literals.
matrix walks made slightly faster by caching a row or column before traversal
#512:
adds sicmutils.mechanics.routhian
, with implementations of Lagrangian->Routhian
, Routh-equations
, Routhian->acceleration
, Routhian->state-derivative
, Lagrangian-state->Routhian-state
and Routhian-state->Lagrangian-state
.
adds missing sicmutils.mechanics.{routhian,time-evolution,noether}
to sicmutils.env.sci
#509:
Fixes a bug with down*Matrix
multiplication, and adds tests for correctness.
Adds sicmutils.matrix.{symmetric?,antisymmetric?}
predicates
The mechanics port continues with sicmutils.mechanics.rigid
:
T-rigid-body
moves to T-body-Euler
with an alias back to its original name. Same situation for Euler-state->L-body
=> L-body-Euler
and Euler-state->L-space
=> L-space-Euler
.
New functions: three-vector-components->antisymmetric
, T-body
, L-body
, L-space
, Euler->omega
, Euler->omega-body
, quaternion-state->omega-body
, quaternion-state->omega-space
, qw-state->L-body
, qw-state->L-space
, T-quaternion-state
#511 focuses on adding more rotations and efficiency to sicmutils.quaternion
. Specifically:
magnitude-sq
and magnitude
are now more efficient.
New functions to get to and from quaternions and various matrix representations: from-rotation-matrix
, ->rotation-matrix
, from-complex-matrix
, ->complex-matrix
, from-4x4-matrix
, ->4x4-matrix
New instances ONE-matrix
, I-matrix
, J-matrix
, K-matrix
, matrix representations of the corresponding quaternion elements.
Similar to the matrix elements, we also now have ONE-tensor
, I-tensor
, J-tensor
, K-tensor
.
#503:
adds sicmutils.mechanics.lagrange/Lagrangian
for building function signatures of Lagrangians.
adds the sicmutils.mechanics.time-evolution
namespace
adds sicmutils.mechanics.lagrange/L-axisymmetric-top
, more efficient than the version in sicmutils.examples.top
Fleshes out sicmutils.mechanics.hamilton
:
New functions: H-state?
, compatible-H-state?
, state->p
, momenta
, P
, literal-Hamiltonian-state
, L-state->H-state
, H-state->L-state
, H-state->matrix
, matrix->H-state
, make-Hamiltonian
, D-phase-space
, Hamiltonian->Lagrangian-procedure
, Hamiltonian->Lagrangian
, flow-derivative
, flow-transform
, standard-map-inverse
, F->K
, J-func
, T-func
, canonical-H?
, canonical-K?
, linear-function->multiplier
, Phi
, Phi*
, qp-canonical?
, polar-canonical-inverse
, two-particle-center-of-mass
, two-particle-center-of-mass-canonical
, transpose-function
, multiplicative-transpose
, symplectic-two-form
, canonical-transform?
, J-matrix
, symplectic?
F->CH
moves to F->CT
(F->CT
is now an alias)
Legendre-transform-fn
becomes Legendre-transform-procedure
and gains more correctness tests, toggled on and off by the *validate-Legendre-transform?*
dynamic variable.
#508 adds sicmutils.mechanics.noether
namespace, with Noether-integral
.
#506 tidies up the build by removing unneeded reader conditionals and replacing renames like core-=
with a proper require of clojure.core
.
#502 begins the port of the remaining items in the scmutils mechanics
package over the Clojure. This PR focuses on sicmutils.mechanics.lagrange
, which contains functions from many files in the original mechanics
folder.
momentum-tuple
moves here from sicmutils.mechanics.hamilton
New functions ->L-state
, ->local
, ->state
,state->n-dof
, time
, state->{q,qdot,qddot}
, coordinates
, velocities
, accelerations
, Q
, Qdot
, Qdotdot
, literal-Lagrangian-state
path->state-path
(alias for the existing Gamma
), Rayleigh-dissipation
, qv->local-path
, Lagrange-equations-first-order
, (with Lagrange-equations-1
alias), Lagrangian->power-loss
, T3-spherical
, L3-central
, Dt-procedure
and the wrapping operator Dt
, Euler-lagrange-operator
(with Lagrange-equations-operator
and LE
aliases), generalized-LE
.
Many of these are aliased into sicmutils.env
. Ask if you think more should be there!
many new built-in Lagrangians: L-Kepler-polar
, L-coupled-harmonic
, L-sliding-pend
, L-pendulum
, L-two-particle
Lagrange-equations
, Lagrangian->acceleration
, Lagrangian->state-derivative
now take a dissipation function
local-state-derivative
aliases the 1-arity version of Lagrangian->state-derivative
New rectangular->polar
, polar->rectangular
, spherical->rectangular
and rectangular->spherical
that operate on coordinates, with associated r->p
(new), p->r
, s->r
and r->s
(new).
#501 moves elliptic-integrals
from sicmutils.special.elliptical-test
sicmutils.special.elliptical
, as it's needed by the upcoming sicmutils.mechanics.pendulum
namespace.
#531:
Fixes a typo in one of the rules in sicmutils.simplify.rules/expand-multiangle
, closing #530
Forces the subexpression walk in pattern.rule/try-subexpressions
with doall
Adds type hints to all remaining Complex
calls in js, to fix issues with advanced compilation (thanks to @mhuebert for finding this)
#515:
tidies up the square
and cube
speedups thanks to a tip from GJS
Converts more (mul x x)
to square
in the derivatives of the sicmutils.generic
namespace.
fixes a bug in the numeric-zero?
check of exponent's derivative.
#503:
Changes the default implementation of square
and cube
for differentials to use (expt <> 2)
etc instead of (* <> <>)
.
This is a big deal! For certain expressions there's a huge blowup when you square a big symbolic term, and taking the derivative of it TWICE is very messy.
With this change, differentials use the chain rule to calculuate the derivative of $x^2$ as $2x*x'$, instead of using the product rule and achieving a SECOND differentiatation of the same form and another multiplication: $xx' + x'x$.
Before a judicious simplify
call I added, this change dropped the runtime of the sicmutils.sicm.ch3-test
suite down by 6x. After the simplify change in sicmutils.examples.top
the tests were still 40% faster in that namespace.
Fixes a bug where the RationalFunction
cube implementation actually called square
.
#532:
Removes the potemkin
dependency by importing only what we need directly into sicmutils.util.def
. This makes sense since our versions add a fork
call so that they work for ClojureScript as well.
Moves all examples
into the tests so that we don't ship them with the library. These will eventually be converted to Clerk notebooks.
Removes the hiccup
dependency.
Upgrades test.chuck
and removes all :include-macros true
calls for that library. Only same/ish
requires them now!
Capitalizes the "Script" in ClojureScript everywhere it appears.
#531:
deps.cljs
entriesThe big highlights for this release are:
Thanks for @borkdude for PRs and help talking through clj-kondo
, SCI etc.
Detailed release notes:
#496:
replaces the function values in sicmutils.expression.compile
with symbols; I hadn't realized before that substituting in symbolic Math/sqrt
, for example, was possible, vs a #(Math/sqrt %)
function value. Compiled functions are now faster!
A simulation run of the double pendulum example in the clerk-demo repository now runs in 350ms vs the former 2.2 seconds, a major win.
Function compilation now pre-simplifies numerical forms encountered inside a function, like (/ 1 2)
, instead of letting them be evaluated on every fn call.
All numerical forms encountered in function compilation are now converted to either double
on the JVM or js/Number
in javascript; this way no BigInt
values etc are left around.
#485 adds a development dependency on Nextjournal's Clerk library, and begins the process of massaging various namespaces into proper literate essays display-able with Clerk. To run these, start a REPL and follow the instructions in dev/user.clj
.
- `sicmutils.calculus.derivative` and `sicmutils.differential` now render as proper literate essays, with TeX bugs fixed.
#497: sicmutils.expression.compile/compile-state-fn
and its non-memoized version can now take an explicit :mode
argument; this will override the dynamically bound *mode*
. Invalid modes supplied via :mode
will cause compile-state-fn
to throw an exception.
#496, sicmutils.expression.compile
:
gains a new, validating compiler-mode
function for fetching the compiler function.
set-compiler-mode!
now actually works. It never did!
New :source
compile mode that returns a source code form. You can either call eval
on this or call sci-eval
to get an SCI-evaluated function with all proper bindings in place.
compile-state-fn
now takes an optional options map, with support for :flatten?
and :generic-params?
keywords. These can be used to tune the shape of the function returned by compile-state-fn
.
#485:
2.17.4
, and the included cljs
version to 1.11.4
. sicmutils.collection
properly handles the new cljs IntegerRange
class.sicmutils.polynomial.factor
now memoizes poly->factored-expression
by default. If polynomial GCD fails inside that function the computation now proceeds with a warning instead of failing.
#492 updates the clj-kondo
linters to emit custom warnings with all metadata from the original token, not just :row
and :col
. This fixes the ability to override or ignore individual warnings.
#490 adds sicmutils.numerical.roots.bisect
with implementations of bisection search, secant search and a mixed method found in scmutils
. These all live under a bisect
function.
The data structure returned is similar to the minimization functions in the sicmutils.numeric.{unimin, multimin}
namespaces. As more root-finding methods come online this should all standardize nicely.
#491 adds sicmutils.mechanics.rotation/M->Euler
, for converting from a rotation matrix to a triple of Euler angles. Now we can successfully round trip.
#489:
Installs g/log
and g/exp
for js/BigInt
instances, enabling g/log2
and g/log10
in the mix.
Removes most js*
calls using coercive-=
and js-mod
. This form is internal and should be avoided.
#484 adds sicmutils.polynomial/from-power-series
, for generating a polynomial instance from some prefix of a (univariate) power series.
up
and down
were applied at compile time, throwing an error.#498 replaces all long-form GPL headers with "SPDX-License-Identifier: GPL-3.0"
.
#485 Bumps the JDK version for Github Actions to 17 from 8.
The big feature of this release is a custom clj-kondo
config for sicmutils. All macros in the library (let-coordinates
, with-coordinate-functions
, all of the pattern matching macros and more) now show proper linter warnings; the pattern matching macros in particular will now show helpful warnings on cases where you've made an easy-to-correct mistake in your pattern syntax.
For example, the following form:
(require '[sicmutils.rule :as r])
(r/rule (+ (? x) (? y)) => (+ (? y odd?) (? x)))
Will provide this inline linter warning, appearing as you type:
Restrictions are not allowed in consequence bindings: odd?
See here for the full list of macros handled by the config.
#477 adds tight integration with the clj-kondo
linter via an exported clj-kondo configuration in the resources
directory. All macros in the library now offer pleasant linting to users. This is especially helpful for the macros in pattern.rule
, which now can offer live feedback to pattern-matching authors.
See doc/linting.md
for details on various warnings reported, and installation instructions for the clj-kondo config.
Thanks to @borkdude for all of his help getting this working, and making this amazing project!
All linter errors and warnings are now addressed, fixed and silenced for the entire codebase, both test
and src
directories.
A new Github Action will run the linter for every PR and push to master, and annotate PRs with linter warnings and errors.
#481 adds a new x-degree
argument to sicmutils.polynomial/univariate->dense
, for padding the result with zeros in the case that you want to guarantee a certain dense degree in the result.
#477:
com.gfredericks/test.chuck
dev dependency upgraded to 0.2.13
to grab its clj-kondo exported config.
pattern.rule
patterns can now handle spliced and unquote-spliced inputs in their symbol position.
#481 fixes a long-standing (test-only) bug in sicmutils.polynomial-test
around palindromic polynomials
#480: sicmutils.numerical.quadrature/definite-integral
now coerces the result of non-compiled integrands in cljs to double. This prevents the @kloimhardt bug where certain paths would produce BigInt
instances and fail in quadrature calls.
in #477, I found the following bugs with the help of the linter:
Deleted the unused sicmutils.differential/d:apply
.
Fixed a bug with sicmutils.expression.render/->JavaScript
not using the second argument to remainder
.
deleted sicmutils.numerical.quadrature.common
in favor of sicmutils.generic/infinite?
Fixed a broken integrator in sicmutils.numerical.quadrature.simpson38
, and fixed the tests to actually stress this code.
Fixed a bug where sicmutils.numerical.quadrature.substitute/exponential-upper
was not actually using its input function!
unused simplify
argument removed from sicmutils.simplify.rules/non-negative-factors!
and all uses.
Bug fix in sicmutils.special.elliptic/jacobi-elliptic-functions
; deep in the gnarly fn, one of the branches returned nil instead of its required values. Thank you, linter!
sicmutils.pattern/template
will no longer error in the 1-arity case when some form contains a binding entry like (? (fn [m] ...))
. Instead, the function will be passed an empty map.
This release takes us a good way toward completing the port of the kernel, the beating heart, of the original scmutils Scheme library. First, the highlights, and then the thematically organized CHANGELOG entries captured in this release.
We now have a full Quaternion implementation! The implementation is built out of the best stuff I could find in every Quaternion library out there, well documented and fully generic. In the future we should be able to specialize various methods to native numerics, making this type very fast.
Lots of new generics, including all remaining trigonometric functions and their inverses. Thanks to John D Cook's 'Bootstrapping a minimal math library' for his inspiration on the defaults and implementation order of these new functions.
The Matrix, Structure and Tensor APIs are now fully ported. This led to some big efficiency boosts, and the ability to solve systems of linear equations with various combinations of matrices, up
and down
structures and row
and column
matrices.
Functional folds! A big rewrite of the floating-point summation routine code led to some (I think) original discoveries about how to write polynomial interpolation, rational function interpolation and Richardson extrapolation as functional folds.
Lots of performance improvements! One of the early examples from SICM involves finding a path that "minimizes action" given some Lagrangian. This example is down from many seconds to 100ms on my machine.
Read on for detailed release notes.
#461 adds sicmutils.quaternion
, with a full arithmetic implementation and the beginnings of a rotation API. Quaternions are implemented like vectors of length 4, and implement all appropriate Clojure protocols. All arithmetic is compatible with all scalars and complex numbers.
Accessors: get-r
, real-part
, get-i
, get-j
, get-k
, complex-1
, complex-2
, ->complex-pair
, ->vector
, three-vector
Predicates: real?
, zero?
, one?
, pure?
, unit?
Constants: ZERO
, ONE
, I
, J
, K
Reader literal #sicm/quaternion
takes a 4-vector or a single entry.
Constructors: make
, from-complex
, spherical
, semipolar
, multipolar
, cylindrospherical
, cylindrical
More: arity
, evaluate
, partial-derivative
, magnitude-sq
, normalize
, commutator
Transcendental functions: exp
log
, cos
, sin
, tan
sinh
, cosh
, tanh
. Many more transcendentals will work, thanks to their default implementations.
Arithmetic and generics: +
, -
, *
, /
, dot-product
, cross-product
, conjugate
, magnitude
, expt
, sqrt
, simplify
, infinite?
, solve-linear-right
, solve-linear
Rotation-related: from-angle-normal-axis
, from-angle-axis
, pitch
, roll
, yaw
, ->angle-axis
#458:
g/negative?
returning false
for literal numbers and symbols. This was required to get g/abs
working for polynomials and rational functions with symbolic coefficients.#448:
g/infinite?
generic with implementations for all numeric types, complex numbers, differential
instances. Defaults to false
for all other types. (Also aliased into sicmutils.env/infinite?
).#449:
All missing trigonometric functions have been filled in sicmutils.generic
and aliased in sicmutils.env
:
acot
asec
acsc
coth
and acoth
sech
and asech
csch
and acsch
All of these have default implementations and derivatives defined. They'll work out of the box for all types with atan
defined (and potentially exp
, sqrt
and log
.)
Thanks to John D Cook's 'Bootstrapping a minimal math library' for his inspiration on the defaults and implementation order of these new functions.
expt
gains a new default implementation for non-native-integral powers, making expt
work for any type with exp
, log
and mul
defined.
sqrt
gains a default implementation for all types implementing exp
, mul
and log
.
All trig functions now have derivatives and docstrings.
New sinc
, tanc
, sinhc
, tanhc
functions live in sicmutils.generic
and are aliased into sicmutils.env
. These are generically defined as (/ (sin x) x)
, (/ (tan x) x)
(and similar with sinh
and tanh
), with correct definitions for 0 and infinite-valued inputs.
These functions all support derivatives as well.
New default acot
implementation in sicmutils.series
.
#469:
sicmutils.matrix
gains:
literal-column-matrix
, literal-row-matrix
for generating slightly tidier matrices of literal entries. (See literal-matrix
for the prior option.)
structure->matrix
converts 2 tensors into explicit matrices.
s:solve-linear-left
, s:solve-linear-right
, s:divide-by-structure
act on 2 tensors. These live in the matrix namespace since they depend on conversions to and from tensors and matrices.
make-diagonal
for generating diagonal matrices with a constant element along the diagonal.
s->m
, s:transpose
and s:inverse
all gain new 2-arities that provides a sane default for ls
.
More efficient matrix invert
and determinant
routines, plus functions to generate type specific custom matrix inversion and determinant routines via classical-adjoint-formula
, general-determinant
.
Linear equation solving via solve
, rsolve
and cramers-rule
.
sicmutils.structure
gains down-of-ups?
, up-of-downs?
, two-up?
, two-down?
, two-tensor?
and two-tensor-info
for working with "2 tensors", ie, structures that contain structural entries of matching orientation and size.
Implements new generics for matrices and structures:
diagonal matrices respond true to v/=
with a scalar if all entries along the diagonal are equal to that scalar.
square matrices can now g/+
and g/-
with scalars; the scalar c
is converted (* c I)
, where I
is an identity matrix of the same dimension as the square matrix.
(g/acot M)
now expands the matrix M
into a nice power series, more efficient than the previous default.
Thanks to solve
and cramers-rule
, the following g/div
combinations now work: matrix/scalar
, scalar/square-matrix
, column-matrix/square-matrix
, row-matrix/square-matrix
, up/square-matrix
, down/square-matrix
, matrix/square-matrix
.
new solve-linear
implementations between square matrices and up
down
, row and column matrices, and between structures and scalars.
new solve-linear-right
between row-matrix+square-matrix, down+square-matrix and scalar+structure.
#456:
sicmutils.polynomial.richardson
discusses this; the namespaces gains richardson-fold
, richardson-sum
and richardson-scan
.#451:
new sicmutils.algebra.fold
namespace:
New folds: kahan-babushka-neumaier
(aliased as kbn
), kahan-babushka-klein
and and kbk-n
macro for generating higher-order kahan-babushka-klein
variants. generic-sum-fold
folds using sicmutils.generic/+
.
sicmutils.util.aggregate/kahan-fold
now lives here, named kahan
.
fold->sum-fn
and fold->scan-fn
generate functions like sicmutils.util.aggregate.{sum,scan}
specialized to the supplied fold. See the docstrings for the multiple arities supported
fold primitives: count
, constant
, min
, max
.
fold combinator join
allows compound folds to be built out of primitive folds.
Upgrades to sicmutils.util.aggregate
:
scanning-sum
renamed to scan
halt-at
deleted in favor of the built-in halt-when
that I didn't know about!
scan
and sum
now both use a dynamic binding, *fold*
, to set the fold they use for aggregation. By default, this is set to the new kahan-babushka-neumaier-fold
.
The three-arity version of sum
now uses transducers, saving a pass over the input range.
pairwise-sum
implements pairwise summation, an error-limiting technique for summing vectors. Use the dynamic binding *cutoff*
to set where pairwise-sum
bails out to normal summation.
Upgrades to sicmutils.rational-function.polynomial
:
The folds in this namespace now follow the fold contract laid out in sicmutils.algebra.fold
, implementing all three arities correctly.
I realized that the fold implementation here should /not/ return a full row every time it processes a previous row; a far better present
implementation would return the best estimate so far. Then you could build a scan
from that fold to see the estimates evolve lazily as new points are added. This has better performance, it turns out, than the original method!
added a bunch to the exposition to make the advantages clear.
Upgrades to sicmutils.rational-function.interpolate
:
fold
interface upgraded, similar to the polynomial interpolation notes.
New bulirsch-stoer-fold
, bulirsch-stoer-sum
and bulirsch-stoer-scan
functions. These are similar to the modified-**
versions but use the bulirsch-stoer
algorithm, instead of modified-bulirsch-stoer
.
modified-bulirsch-stoer-fold-fn
renamed to modified-bulirsch-stoer-fold
, to match the naming scheme of other "folds" in the library.
modified-bulirsch-stoer-fold
renamed to modified-bulirsch-stoer-sum
, to match the convention that "reducing a sequence with a fold" is called "summing" the sequence. I can see this changing down the road...
See context-opts
for instructions on how to enable sicmutils.algebra.fold/kbk-n
in the SCI environment (you'll need to turn on access to js/Math
or java.lang.Math
).
#450:
Adds sicmutils.series/harmonic-series
, the infinite series of harmonic numbers
moves sicmutils.numerical.elliptic
to the sicmutils.special
package, as sicmutils.special.elliptic
.
New sicmutils.special.factorial
namespace! sicmutils.util.permute/factorial
moves here, and the forgotten duplicate sicmutils.generic/factorial
is now gone.
falling-factorial
, rising-factorial
, double-factorial
, multi-factorial
, subfactorial
, binomial-coefficient
, stirling-first-kind
, stirling-second-kind
.New sicmutils.util.permute/multichoose
function, implementing the definition described here.
better number-of-combinations
impl in sicmutils.util.permute
, using sicmutils.special.factorial/falling-factorial
sci bindings forsicmutils.special.factorial
, sicmutils.util.permute
.
#458: slight efficiency improvement in sicmutils.polynomial.gcd/->content+primitive
.
#468:
adds sicmutils.polynomial/touchard
, implementing a constructor for the type of polynomial known as a "complete Bell polynomial" or "Touchard polynomial".
adds sicmutils.special.factorial/bell
for computing the nth Bell number
sicmutils.series/bell-series
returns an infinite sequence of bell numbers.
#463:
adds a new 1-arity to sicmutils.matrix/characteristic-polynomial
that returns an actual polynomial instance. Creating this polynomial once and calling it many times is much more efficient. Closes #209.
adds sicmutils.series/function->
, for generating a Maclaurin series from a function.
#453:
sicmutils.polynomial/from-points
and sicmutils.rational-function/from-points
for generating Polynomial
and RationalFunction
instances from sequences of points.#450 adds sicmutils.series/harmonic-series
, the infinite series of harmonic numbers
#455 makes sicmutils.util.aggregate/scan
and sicmutils.algebra.fold/fold->scan-fn
slightly more efficient by dropping the first element of the returned sequence before mapping the present
function.
#451:
Fixed a type inference warning in Clojurescript in sicmutils.complex
.
Added support for sicmutils.util.def
and its fork
macro to the default SCI environment provided by SICMUtils. Helpful for macro-writing!
sicmutils.numerical.quadrature.adaptive
now uses the dynamically bound sicmutils.util.aggregate/*fold*
to accumulate its numerical integral pieces, instead of a hardcoded kahan-sum
.
sicmutils.numerical.quadrature.bulirsch-stoer
now uses the functional scan versions of polynomial and rational function interpolation, as these are a bit faster than the originals!
#474:
g/quotient
now supports inexact inputs, as LONG as the inputs are equal up to sign. So (g/quotient 1.2 -1.2)
now returns -1
instead of throwing.
#469: new g/acot
generic method installed for Operator instances.
#471:
installs the complex GCD implementation into the generic system and modifies it to work with real/complex pairs.
tweaks the default gcd implementation so that two identical values x
, even if they are floating point, will return x
from (gcd x x)
. (default gcd in sicmutils.euclid
can handle cases now where the terms are equal and of opposite sign.)
adds exact-divide
handling of non-integral numbers when the inputs are either equal or of opposite sign.
#398 adds a sicmutils.generic/gcd
implementation for complex numbers, closing the long-standing #58. Thanks to @adamhaber for this!
#447 contains a grab-bag of fixes and additions, many related to complex numbers:
Use Math/E
instead of (Math/exp 1)
for euler's constant in sicmutils.env
.
Fix bug in sicmutils.calculus.indexed
, in a case where either input was missing an up
or down
index type.
symbolic dot-product
and inner-product
inner-product
now defaults to dot-product
for scalar instances. This is correct for all numeric types we currently have, since complex
is the only tough case, and it has real coefficients.
simplify now does NOT freeze expressions before simplifying. This allows complex numbers to survive simplification, since they freeze to (complex <re> <im>)
.
big rewrite in sicmutils.simplify.rules
, to convert all of the frozen matchers like (complex 1 2)
into matchers that actually bind to a complex number.
more rules in complex-trig
, it can now handle bigger products inside of sin
and cos
multiplied by I
.
#448:
The infix, TeX and JavaScript renderers (->infix
, ->TeX
and ->JavaScript
) all properly render ##Inf
and ##-Inf
. Infix uses the Unicode symbol ∞, while ->TeX
uses the LaTeX command \infty
. Javascript's Infinity
stands in for ##Inf
in generated JS code.
Complex numbers now respond true
to g/negative?
if their imaginary component is zero and real component is negative, false otherwise.
g/+
, g/-
, g//
no longer short circuit if there is a NUMERIC zero on either side. This was causing bugs in cases where we allow, say, a scalar to be added to a quaternion, and auto-convert the scalar right there (so it adds only to the real part). OR in cases, like in the matrix PR, where we convert the scalar in addition to <scalar>*I*
.
sicmutils.matrix
tests that were not well typed.The default expt
implementation is now available as a function to call directly (sicmutils.generic/default-expt
) without going through the dispatch system.
#447 adds various improvements to sicmutils.complex
:
complex implementations for dot-product
between complex and real types
Fixed reflection warnings with ComplexFormat
in complex parsing code
complex zero?
now returns true for inputs like (complex -0.0 -0.0)
, where a negative zero lives in the real or imaginary slots
new sicmutils.complex/-I
binding, set to (g/negate c/I)
g/expt
for complex numbers optimizes the inputs equal to I
by returning exact 1, -1, I
or -I
depending on the input. This applies to g/square
and g/cube
as well.
#443:
Implements IKVReduce
and Reversible
for structures. This enables rseq
and reduce-kv
to work with structures.
Removes a reduced
shortcut condition in sicmutils.generic/*
that was causing multiplications of the form (* 0 0 (up 0 0))
to shortcut and return 0
instead of the appropriate structural form.
#438:
converts doall
calls to run!
, dorun
, doseq
or mapv
where applicable. In cases where we were trying to force side effects (mostly in the tests), this change prevents the environment from retaining the full sequence. This will save memory!
adds missing tests from connection.scm
to sicmutils.calculus.connection-test
, stressing pages 205 - 213 from MTW, Gravitation.
#434: allow pattern matching forms to successfully bind to nil
or false
.
#397: sicmutils.calculus.manifold/typical-coords
now returns generated coordinate symbols that start with the same symbol as the coordinate system's prototype, like:
(typical-coords R2-polar)
;;=> (up x065308 x165309)
(typical-coords
(with-coordinate-prototype R2-polar (up 'r 'theta)))
;;=> (up r65312 theta65313)
integration-opts
to sicmutils.mechanics.lagrange/Lagrangian-action
. All options are passed on to definite-integral
. By default, parametric-path-action
passes :compile? false
, since we do NOT want to compile the polynomial.#469 renames square-structure->
to two-tensor->
, and square-structure-operation
to two-tensor-operation
. These functions now work with rectangular 2 tensors, not just square.
#456:
sicmutils.mechanics.lagrange/{Γ,Γ-bar}
are removed in favor of the existing Gamma
and Gamma-bar
functions. The sicmutils.env
aliases are gone as well.
sicmutils.mechanics.lagrange/Lagrange-interpolation-function
now returns an actual polynomial instance. Because polynomials support IFn
and respond to the derivative operator D
, this makes the find-path
example on pages 22/23 of SICM run about 5x faster.
#451:
sicmutils.util.stream/scan
deleted in favor of sicmutils.util.aggregate/scan
with a dynamic binding for *fold*
to customize.#469 fixes an infinite loop with sicmutils.matrix/some
.
Renames square-structure->
to two-tensor->
, and square-structure-operation
to two-tensor-operation
. These functions now work with rectangular 2 tensors, not just square.
New g/acot
generic method installed for Operator instances.
#463:
expt
called with a negative base and non-integral power now properly returns a complex number instead of ##NaN
.
symbolic =
now behaves correctly and accumulates an expression of nested and
s, vs before. The previous behavior would convert (= 'a 'b 'c')
to (= (= 'a 'b) 'c')
, which is NOT correct. (if (= 'a 'b)
is true, then the expression evaluates to false
, since (= true 'c')
is false.)
#445 fixes a bug where structures and other seq-able types were interpreted as sequence matchers.
In pattern.match
and all rules, things that respond true to sequential?
but not seq?
or vector?
(many of the sicmutils types, like structures and the upcoming Quaternion type) were being converted to seq
and treated as sequence matchers vs literal matchers. This no longer happens, and structures etc are treated as literal matchers.
#442 fixes #441 by upgrading the implementations of sicmutils.util.permute/{factorial,number-of-combinations}
to be able to handle large inputs. Thanks to @swapneils for the report.
#440:
Modifies (g/exp 0)
to return an exact 1, vs the previous 1.0
.
Fixes a bug in sicmutils.rules/exp-contract
leftover from the port from Scheme. Thanks to @adamhaber for pointing this out!
#443:
atan
implementation for symbolic numbers is now careful not to return a floating point number in the case of a 0 argument in the second position. Additionally, it now returns symbolic pi
or 0 in the case of 0
in the y argument for positive and negative x
argument, respectively, and symbolic (/ pi 2)
or (- (/ pi 2))
for a 0 x
argument and respective positive or negative y
argument.#458:
Polynomials and rational functions now correctly unwrap Literal
coefficients in ->expression
. Without this, the resulting expressions would not correctly respond to simplify
calls.
sicmutils.rational-function/from-points
now correctly builds its function. Before, it was unhygienic; if 'x
appeared in the coefficients the results would be incorrect.
Small bugfix release to push out #396 .
#396:
fixes a bug in the SCI version of define-coordinates
which didn't allow
any rebinding of manifolds.
Removes the bindings
key from sicmutils.env.sci/context-opts
.
https://github.com/babashka/sci/issues/637 is a bug with variable rebinding
that occurs when :bindings
is in play. Instead of relying on this key,
evaluate (require '[sicmutils.env :refer :all])
against your SCI
environment to get all bindings.
bumps the default version of SCI to 0.2.7.
This release cleans up the differential geometry utilities in SICMUtils and fixes a couple of bugs that prevented the Einstein Field Equations from running. These now work well, and very fast!
define-coordinates
macro#sicm/complex
reader literal:#sicm/complex [1.2 3.6] ;; 1.2+3.6i
#sicm/complex [1.2] ;; 1.2
#sicm/complex 1.4 ;; 1.4
#sicm/complex "1.2 + 3.6i" ;; 1.2+3.6i
A big thanks to @phasetr for pushing on this in this discussion: https://github.com/sicmutils/sicmutils/discussions/380
#348:
Adds a new single arity version of
sicmutils.util.permute/permutation-parity
, which returns the parity of a
permutation relative to its sorted version.
sicmutils.complex/complex
can now take a single string argument in both
Clojure and Clojurescript.
Expands the complex number literal parser to take these forms, in addition to the previously-supported string argument:
#sicm/complex [1.2 3.6] ;; 1.2+3.6i
#sicm/complex [1.2] ;; 1.2
#sicm/complex 1.4 ;; 1.4
#sicm/complex "1.2 + 3.6i" ;; 1.2+3.6i
#393:
Forms like (let-coordinates [(up x y) R2-rect] ...)
will now work even if up
is not present in the environment. Previously this syntax was valid, but only if up
had been imported.
Adds the sicmutils.calculus.coordinate/define-coordinates
macro, also aliased into sicmutils.env
. This macro allows you to write forms like
(define-coordinates (up t x y z) spacetime-rect)
(define-coordinates [r theta] R2-polar)
and install a set of bindings for a manifold's coordinate functions, basis vector fields and basis form fields into a namespace. This is used liberally in Functional Differential Geometry. (You might still prefer let-coordinates
for temporary binding installation.)
Converts many of the sicmutils.fdg
test namespaces to use the new define-coordinates
macro, making for a presentation closer to the book's.
Fixes a Clojurescript warning in sicmutils.util
warning due to redefinition of clojure.core/uuid
#381:same.ish/Approximate
implemented for sicmutils.structure/Structure
, allowing ish?
comparison of up
and down
structures with approximate entries. Require sicmutils.generator
for this feature. (NOTE: because protocols are implemented for the LEFT argument, (ish? <vector> (down ...))
will still return true if the values are approximately equal, even though a <vector>
is technically an up
and should NOT equal a down
. Do an explicit conversion to up
using sicmutils.structure/vector->up
if this distinction is important.)
#381:
Section 7.3 of FDG implemented as tests in sicmutils.fdg.ch7-test
.
#382 adds tests for all code forms in Chapter 8 of FDG.
Many new tests and explorations ported over from covariant-derivative.scm
. These live in sicmutils.calculus.covariant-test
.
#384:
Adds sicmutils.fdg.ch9-test
, with tests for all forms from FDG's 9th chapter.
Tests from sicmutils.fdg.einstein-test
now all work, and quite fast. The functions in this namespace comprise some of the exercises from FDG chapter
9. (Einstein's Field Equations hung until this PR... getting these working
is a huge achievement for me, and, in some sense, the final milestone of the
Big Port from scmutils.)
Adds sicmutils.function/memoize
, a metadata-and-function-arity preserving version of clojure.core/memoize
.
Adds new manifold?
and manifold-family?
functions in sicmutils.env
and sicmutils.calculus.manifold
. These are enabled by new :type :sicmutils.calculus.manifold/{manifold,manifold-family}
keys in the appropriate structures in the manifold namespace. Manifolds and manifold families will now respond with these keywords to sicmutils.value/kind
.
#386:
Aliases sicmutils.mechanics.hamilton/phase-space-derivative
into sicmutils.env
, and adds sicmutils.sr.frames/base-frame-maker
. The latter function makes it easier to write reference frames like the-ether
, as with the home
variable in chapter 11 of FDG.
Adds all code listings from chapters 10 and 11 of FDG as sicmutils.fdg.{ch9,ch10}-test
.
sicmutils.calculus.coordinate/generate
moves to sicmutils.calculus.manifold/c:generate
; this supports a bugfix where 1-dimensional manifolds like R1-rect
, aka the-real-line
, return a coordinate prototype of a single element like t
instead of a structure with a single entry, like (up t)
. Thanks to @phasetr for the bug report that led to this fix, and @gjs for finding and fixing the bug.:type
key. We do this for manifold families and manifold points, as two examples. Now, instead of recursing into the values, the system will correctly throw an error. (You can fix this by using a defrecord
instead of a map and implementing sicmutils.differential/IPerturbed
.)#381:
same.ish/Approximate
now defers to sicmutils.value/=
for equality between Symbol
and other types. This lets ish?
handle equality between symbols like 'x
and literal expressions that happen to wrap a single symbol.
Cartan->Cartan-over-map
now does NOT compose (differential map)
with its internal Cartan forms. This fixed a bug in a code listing in section 7.3 of FDG.
timeout exceptions resulting from full GCD are now caught in tests using sicmutils.simplify/hermetic-simplify-fixture
. Previously, setting a low timeout where simplification failed would catch and move on in normal work, but fail in tests where fixtures were applied
#382:
name
argument to sicmutils.operator/make-operator
optional. name
now defaults to '???
.#384:
in sicmutils.calculus.indexed
, with-argument-types
and with-index-types
now both correctly set the arity of the returned function, in addition to the argument types or indices. sicmutils.function/arity
will now work correctly with indexed or typed functions.
The sicmutils.calculus.manifold/ICoordinateSystem
now has a uuid
function, for internal comparison of coordinate systems. This is here so that points can cache coordinate system representations by UUID. Before this change, changing the coordinate prototype, or attaching metadata to a coordinate system would break its cache entry in manifold points. (This was the killer for the Einstein Field Equations!)
sicmutils.calculus.manifold/{coordinate-prototype,with-coordinate-prototype}
now store and retrieve the coordinate prototype from metadata. This plus the previous change allows manifold points to correctly cache their coordinate representations.
sicmutils.calculus.manifold/manifold
acts as identity on manifolds now. Previously it only worked on coordinate systems.
#376 adds more type hints to the ratio.cljc
namespace. This fully solves the advanced compilation issues we were seeing.
#374: Demos, thanks to @sigmaxipi!
#379 fixes typos in a couple of the equations in richardson.cljc
, closing #377. Thanks to @leifp for the report.
Incremental release that bumps the Fraction.js dependency to 4.1.1. This includes https://github.com/cljsjs/packages/pull/2190, which makes bigfraction.js
compatible with advanced compilation.
Fraction.js
dependency to 4.1.1
.This is an incremental bugfix release to get Clojurescript advanced compilation into shape.
#371:
fixes a subtle bug with extern inference on fraction.js/bigfraction.js
. Thanks to @sigmaxipi for this report!
removes overridden factory constructors like ->Polynomial
. I had originally done this for functions that held a metadata field, so that the user could leave it out and have it default to nil
... but advanced Closure compilation can't understand the ns-unmap
call, so it has to go.
Many unary functions on Operator
, Structure
, Series
, PowerSeries
, Polynomial
and RationalFunction
now preserve metadata. Binary functions between two instances of any of these still return a new object with metadata == nil
.
(If you have any questions about how to use any of the following, please ask us at our Github Discussions page!)
This release focused on improving the expressiveness and performance of the three simplification engines in SICMUtils:
sicmutils.polynomial
and sicmutils.rational-function
are now quite well fleshed out, with full polynomial and rational function APIs and many generics.
The polynomial and rational function simplifiers work by round-tripping expressions through these types, depending on each namespace to emit symbolic expressions in "canonical form". This process is now much faster! On one important Bianchi Identity benchmark in sicmutils.fdg.bianchi-test
, one test that formerly took close to 30 minutes now runs in 30 seconds, and all see a 60-fold improvement.
By default, these simplifiers emit expressions with all terms multiplied out; the new factor
function in sicmutils.env
lets you factor expressions, overriding this default.
The rule-based simplifier is now based on a powerful pattern matching engine, implemented in pattern.match
and pattern.rule
. sicmutils.simplify.rules
now contains every rule and possible customization from the original scmutils codebase.
There is a lot in this release, all motivated by performance. Please read on for the detailed notes, and enjoy version 0.19.0!
#353 introduces a powerful new simplifier, ported from the new-simplify
procedure in simplify/rules.scm
of the scmutils library. There are now a BUNCH of new rulesets and rule simplifiers in sicmutils.simplify.rules
!
The next step with these is to massage them into separate bundles of rules that users can mix and match into custom simplifiers for objects like abstract matrices, abstract bra and ket structures, up and down, booleans (for representing equations and inequalities) and so on.
#349 introduces a new pattern matching system, built out of matcher combinators. All of the rules in sicmutils.simplify.rules
now use the new syntax offered by the library. Some notes:
pattern.match
defines a number of "matcher combinators"; these are functions that take a map of bindings, a data input and a success continuation and either succeed by calling their continuation, or fail. Out of the box, the library provides fail
, pass
, with-frame
, update-frame
, predicate
, frame-predicate
, eq
, bind
, match-when
, match-if
, or
, and
, not
, segment
and sequence
.
Additionally, any combinator that takes another combinator can ALSO take a pattern form like '?x
. See pattern.syntax
for the full, rich range of syntax allowed. These are all functions, so you'll have to quote your symbols at this stage.
Passing a matcher combinator to pattern.match/matcher
to generate a matcher object. This is a function from some data
input to a map of bindings on success, or an explicit pattern.match/failure
object on failure. Test for failure with pattern.match/failed?
.
A combination of a matcher and a "consequence function" is called a "rule". A consequence is a function that takes a binding map and either returns a new result or fails by returning nil
or false
. (Don't worry, you can succeed with these values too by wrapping them in sicmutils.rule/succeed
.)
Rules are the heart of the whole simplification mechanism in sicmutils! To learn about how to build these, see the documentation for pattern*
, pattern
, consequence
, template
, rule*
and rule
.
pattern.rule
gives you some starter rules, and many combinators you can use to build more and more powerful and complex sets of rules. These are pass
, fail
, predicate
, return
, branch
, choice*
, choice
, pipe*
, pipe
, n-times
, attempt
, guard
, iterated
, while
, until
, fixed-point
and trace
.
Rules are nice for rewriting entire expressions recursively, from the bottom up or top down. This is called "term rewriting". A big motivation for this rewrite was to make it easy to build custom term rewriters for types like abstract matrices or abstract up and down structures. You can use your rules to rewrite structures recursively with bottom-up
, top-down
, iterated-bottom-up
and iterated-top-down
. ruleset*
, ruleset
, rule-simplifier
and term-rewriting
capture some common patterns the library uses to go from rules => term rewriters.
If you want ideas about how to use the pattern matching library to rewrite expressions, see sicmutils.simplify.rules
for many examples.
#354 adds SCI support for all macros and functions in the new pattern matching namespaces, and adds these to the namespaces exposed via sicmutils.env.sci
.
#341 takes on a large rewrite of the rational function and polynomial simplfiers. One goal of this project was to improve the performance of the Bianchi Identities in sicmutils.fdg.bianchi-test
, and I'm happy to say that they are now a good bit faster than the original scmutils implementation.
sicmutils.polynomial
and sicmutils.rational-function
are now solid data structures of their own, with many operations installed into the generic system. These are now valuable and useful outside of their role in the simplifier.
This was a large project, and many small improvements and bugfixes snuck in. Here is the full list:
v/kind
now works for sorted-map
instances.
GCD in Clojurescript is now fast and efficient between all combinations of js/BigInt
and js/Number
, and in Clojure between all combinations of clojure.lang.BigInt
, BigInteger
, Long
and Integer
.
on the JVM, GCD now works properly with rational numbers. Previously anything non-integral would return 1
; now (gcd 1/2 1/3)
properly returns 1/6
.
g/exact-divide
now succeeds for all non-exact ::v/scalar
types (symbols, floats, etc) either if the denominator is zero, or if the two arguments are equal. Else, it throws, just like before.
A multi-arity call to sicmutils.generic/*
now stops if it encounters a 0, rather than attempting to multiply all remaining items by 0.
The default function for sicmutils.generic/lcm
protects against overflow by dividing only a single one of its arguments a
and b
by (gcd a b)
.
(g/lcm 0 0)
now properly returns 0.
New sicmutils.util.aggregate/{monoid,group}
functions let you build multi-arity aggregations out of binary combination functions, with an option to bail early at "annihilator" values, like 0 for multiplication.
New multi-arity lcm
and gcd
implementations for symbolic expressions appropriately handle 0
and 1
on either side, as well as the case where both arguments are equal.
In the sicmutils.numsymb
namespace, thanks to monoid
and group
, the '*
, '/
, '-
, '+
, 'or
, 'and
, 'gcd
, 'lcm
and '=
operations now have efficient multi-arity implementations that stop computing when they receive an annihilator, like 0
for multiplication or true
for or
. Access these via (sicmutils.numsymb/symbolic-operator <symbol>)
.
sicmutils.series/PowerSeries
gains arg-scale
and arg-shift
functions; these are identical to sicmutils.function/arg-{scale,shift}
, but preserve the PowerSeries
type. (#367 proposes making these functions generic.)
New sicmutils.ratio/IRational
protocol, with numerator
and denominator
functions implemented for ratios and for the RationalFunction
data type. These two are now exposed in sicmutils.env
.
sicmutils.simplify.rules/*divide-numbers-through-simplify?*
is now true
by default; numbers in the denominator will now automatically pull up into the numerator. All tests now reflect this setting.
Any analyzer generated from sicmutils.expression.analyze
can now act on both bare, unwrapped expressions (raw lists etc) and on sicmutils.expression.Literal
instances. This means that you can now call sicmutils.simplify/{*rf-simplify*,*poly-simplify*}
as functions and canonicalize some form with either simplifier without triggering a full simplification. A small win, but ice.
sicmutils.polynomial.factor
got a major rewrite, and now exposes a few functions like poly->factored-expression
, factor-expression
and factor
.
factor
is tremendously useful! Call factor
(it's aliased into sicmutils.env
) on any expression to factor out all possible terms. This makes it much easier to see where there is some cancellation lurking, in, say, some expression you know should equal zero (a residual).bugfix: sicmutils.expression.Literal
instances now compare their contained expression via sicmutils.value/=
.
sicmutils.rules/constant-elimination
can now eliminate constants from expressions with any arity, not just binary forms.
Now, the three big namespaces... sicmutils.polynomial
, sicmutils.rational-function
and sicmutils.polynomial.gcd
all got a big overhaul.
sicmutils.polynomial
notes:
Polynomial
uses a new sparse representation for its "power product" term; this, plus an arithmetic rewrite, makes the whole system much faster for larger numbers of variables (for all #s, really).
Polynomial
instances implement many more Clojure(script) protocols. They can hold metadata; they can be evaluated as functions of their indeterminates, and seq
now returns a sequence of terms.
Polynomial
extends sicmutils.function/IArity
and differential/IPerturbed
, so you can use sicmutils.function/arity
, and take derivatives of functions that return polynomials.
In their arithmetic, Polynomial
instances will drop down to bare coefficients whenever some multiplication or addition removes all indeterminates. All binary arithmetic exposed in the namespace can handle non-Polynomial
instances on either or both sides, so this is fine. Coefficients are treated as constant polynomials.
The namespace holds many new functions. Some choice ones are:
constructors: make
, constant
, linear
, c*xn
, identity
, and new-variables
accessor functions: arity
, degree
, coefficients
, leading-term
, leading-coefficient
, leading-exponents
, leading-base-coefficient
, trailing-coefficient
, lowest-degree
predicates: monomial?
, monic?
, univariate?
, multivariate?
, negative?
functions to generate new polynomials: map-coefficients
, map-exponents
, scale
, scale-l
, normalize
, reciprocal
, drop-leading-term
, contract
and extend
alongside contractible?
, lower-arity
, raise-arity
, with-lower-arity
, arg-scale
, arg-shift
arithmetic: negate
, abs
, add
, sub
, mul
, square
, cube
, expt
, divide
along with divisible?
, evenly-divide
, pseudo-remainder
, and lots of functions installed into the generic arithmetic system.
different ways to evaluate polynomials: evaluate
, horner-with-error
calculus! partial-derivative
and partial-derivatives
are alive and well, and work with the D
operator.
Functions to get in and out of polynomials from other types: univariate->dense
, ->power-series
, expression->
, ->expression
sicmutils.polynomial.gcd
also got a rewrite; it's fairly clear to read now, and prepared for the eventual addition of the sparse multivariate GCD routine that scmutils uses. There are some efficiency gains here too that let us turn a number of tests back on, or demote them from :long
markers.
sicmutils.rational-function
notes:
RationalFunction
instances implement many more Clojure(script) protocols. They can hold metadata; they can be evaluated as functions of their indeterminates, and seq
now returns a pair of numerator
, denominator
.
RationalFunction
extends sicmutils.function/IArity
and sicmutils.ratio/IRational
, so our generic arity
, numerator
and denominator
work on these instances.
Here are some new functions from the RationalFunction
namespace:
constructor: make
, drops to polynomial or coefficient where needed just like Polynomial
functions
functions to generate new rational functions: arg-scale
, arg-shift
predicates: negative?
arithmetic: negate
, abs
, add
, sub
, mul
, square
, cube
, expt
, invert
, div
, gcd
, and many functions installed into the generic arithmetic system.
evaluation via evaluate
calculus! partial-derivative
and partial-derivatives
are alive and well, and work with the D
operator.
Functions to get in and out of rational functions from symbolic expressions: expression->
, ->expression
.
#358:
Adds a more efficient literal-derivative
implementation to sicmutils.abstract.function
, making the Bianchi identity benchmarks run 40% faster.
In Clojurescript, Range
instances now implement sicmutils.value.Value
and sicmutils.differential.IPerturbed
, allowing them to be returned from derivative-taking functions
Major, unexpected performance improvement - it turns out sicmutils.value/number?
was quite slow in Clojure (less so in Clojurescript). Changing this function from an isa?
check to a series of explicit instance?
checks cut the build time in half. This makes the numeric tower less extensible... but it wasn't terribly extensible to start with, and needs some attention to make it so. A big win!
The Bianchi identity benchmarks have all been updated to reflect the big performance improvements achieved here, thanks to the wonderful Tufte profiling library from @ptaoussanis. The remaining very slow piece in the simplifier is the implementation of g/add
for polynomial instances. #341 will improve this situation.
#360 introduces a number of performance improvements to the sicmutils.differential.Differential
implementation, primarily in terms:+
and terms:*
. thanks again to @ptaoussanis and the Tufte profiling library for helping me track these down.
#357:
Adds the ability to do incremental simplification, every time an operation is performed involving a symbolic expression. Bind sicmutils.numsymb/*incremental-simplifier*
to a function from raw expression -> raw expression, like sicmutils.simplify/simplify-expression
or any of the rules in sicmutils.simplify.rules
to enable this behavior.
Expands the sicmutils.expression.analyze
API with the functions default-simplifier
, expression-simplifier
, initializer
, expression-analyzer
and auxiliary-variable-fetcher
. See the API documentation for detailed notes on how to do interactive expression analysis and simplification with these new tools.
by default, each simplification pass uses both rational function and polynomial canonicalization. This brings the simplifier into line with the scmutils simplifier.
#353:
Adds a new sicmutils.util.logic
namespace with an assume!
function that allows rules to log assumptions when some simplification like (sqrt (square x))
might have to choose one of multiple possible simplifications ((non-negative? x)
, in this example).
This function simply logs the assumption for now, instead of performing any checks. now. Turn off assumption logging with the dynamic variable *log-assumptions?*
in that namespace.
new sicmutils.value/almost-integral?
returns true if its argument is VERY close to an integral value, false otherwise.
Efficient symmetric-difference
implementation in sicmutils.util.vector-set
(#346)
#369:
Removes JVM dependencies on Guava and nrepl.
Removes sicmutils.env/sicmutils-repl-init
; this is only used by lein repl
, and we now accomplish the same task with the :repl-options
entry in project.clj
.
Makes sicmutils.polynomial.{factor,gcd}
available to SCI via the sicmutils.env.sci
namespace
moves a few namespaces to more valid locations, now that the rational function and polynomial namespaces are tidied:
sicmutils.numerical.interpolate.polynomial
-> sicmutils.polynomial.interpolate
sicmutils.numerical.interpolate.richardson
-> sicmutils.polynomial.richardson
sicmutils.numerical.interpolate.rational
-> sicmutils.rational-function.interpolate
#358:
Converts the Clojurescript test build and REPL command from lein-cljsbuild
to shadow-cljs
. This enables more formerly-slow tests for Clojurescript; these are now fast enough to run, thanks to the performance improvements described below.
Upgrades our Timbre logging dependency to version 5.1.2, and SCI to 0.2.5
#353:
expression->stream
, expression->string
, print-expression
, pe
move from sicmutils.simplify
to sicmutils.expression
, and are now aliased in sicmutils.env
.
pattern.rule/guard
now fails if its rule argument fails; previously it wrapped the result in attempt
, and would return its original input on failure.
fixed a heisenbug in sicmutils.expression.analyze/make-analyzer
where, in Clojurescript, using expressions containing a js/BigInt
as a hashmap key caused certain simplifications to fail. (This is vague, but the bug was really subtle.) The fix was to make sure we freeze keys in the symbol cache. This is now noted in the function body.
This release focused on porting over all of the material required to run every piece of code from Sussman and Wisdom's "Functional Differential Geometry". The namespaces are lightly documented; the situation is better than the original library, but will only get better as I work through the material and add commentary.
There is a huge amount of functionality and material here! We can run many examples from general and special relativity, and the tests are full of exercises from the classic "Gravitation" book by Misner, Thorne and Wheeler (MTW).
Notable changes from the rest of the library:
Operator
instances are slightly more efficient with their addition and multiplication, handling zero?
and one?
cases appropriately
Structure
s can now hold metadata
We've extended the SICMUtils generics to Clojure's Map and Set data structures. These can now combine with +
. Maps are treated as sparse infinite-dimensional vector spaces, and can multiply with symbolic or numeric scalars.
ModInt
instances are now correctly equal to numbers (when those numbers mod down to the ModInt
instance's residue).
The next major change will be an overhaul of the simplifier to make it work fast enough to solve Einstein's field equations in a reasonable amount of time, maybe even in the browser. Polynomial GCD is slow, but #341 will make it fast.
On to the detailed notes!
From #339:
The new sicmutils.calculus.covariant/Lie-D
can compute the Lie derivative for coordinates.
sicmutils.calculus.frame
lets us create relativistic reference frames for investigating special relativity problems. This namespace aliases the following functions into sicmutils.env
: 'frame?', make-event
, event?
, claim
, coords->event
, event->coords
, ancestor-frame
, frame-name
, frame-owner
and frame-maker
.
sicmutils.calculus.hodge-star
implements the Hodge star operator from chapter 10 of Functional Differential Geometry, plus Gram Schmidt orthonormalization. This namespace aliases the following functions into sicmutils.env
: Gram-Schmidt
, orthonormalize
and Hodge-star
.
sicmutils.calculus.indexed
ports over the scmutils work on indexed objects and typed functions. This namespace aliases the following functions into sicmutils.env
: argument-types
, with-argument-types
, index-types
, with-index-types
, typed->indexed
, indexed->typed
, typed->structure
, structure->typed
, i:outer-product
and i:contract
.
sicmutils.calculus.manifold
gains coordinate-system?
, which (predictably) returns true if its argument is a coordinate system, false otherwise. chart
and point
also take relativistic reference frames in addition to coordinate systems; the returned function converts to and from coordinates and events, rather than coordinates and manifold points.
Div
, Grad
, Curl
and Lap
move from sicmutils.calculus.derivative
to sicmutils.calculus.vector-calculus
. This namespace also contains versions of these operators from Functional Differential Geometry. This namespace aliases the following functions into sicmutils.env
: divergence
, curl
, gradient
and Laplacian
(along with the others mentioned).
lots of new namespaces available in sicmutils.env.sci
, soon to be deployed to Nextjournal: sicmutils.calculus.{hodge-star, indexed, vector-calculus}
, and sicmutils.sr.{boost,frames}
.
sicmutils.sr.boost
describes boosts from special relativity, covered in chapter 11 of Functional Differential Geometry. This namespace aliases the following functions into sicmutils.env
: make-four-tuple
, four-tuple->ct
, four-tuple->space
, proper-time-interval
, proper-space-interval
, general-boost
, general-boost2
and extended-rotation
.
sicmutils.sr.frames
implements relativistic reference frames from special relativity, covered in chapter 11 of Functional Differential Geometry. This namespace aliases the following functions into sicmutils.env
: make-SR-coordinates
, SR-coordinates?
, SR-name
, make-SR-frame
, the-ether
, boost-direction
, v:c
, coordinate-origin
, add-v:cs
and add-velocities
.
From #338:
sicmutils.fdg.bianchi-test
verifies the Bianchi identities; this was a challenge posed by GJS, and getting it working exposed a few bugs and triggered the rest of the work in this PR. Thank you, GJS!
covariant-derivative
now properly handles the case of functions with argument types attached.
added covariant-differential
to sicmutils.calculus.covariant
.
aliased all functions from various namespaces in sicmutils.calculus
into sicmutils.env
.
adds sicmutils.calculus.metric
, with the following functions exposed in sicmutils.env
:
coordinate-system->metric-components
, coordinate-system->metric
, coordinate-system->inverse-metric
, literal-metric
, components->metric
, metric->components
, metric->inverse-components
, metric-over-map
, lower
, vector-field->oneform-field
, drop1
, raise
, oneform-field->vector-field
, raise1
, drop2
, raise2
, trace2down
, trace2up
, sharpen
, S2-metric
sicmutils.calculus.metric/invert
is exposed as metric:invert
to match the scmutils naming scheme.
adds sicmutils.calculus.connection
, with the following functions exposed in sicmutils.env
:
make-Christoffel-1
, metric->Christoffel-1
, metric->Christoffel-2
, literal-Christoffel-1
, literal-Christoffel-2
, metric->connection-1
, metric->connection-2
, literal-Cartan
, structure-constant
#337:
adds sicmutils.calculus.curvature
, with these new functions and many tests from the classic "Gravitation" book: Riemann-curvature
, Riemann
, Ricci
, torsion-vector
, torsion
and curvature-components
form fields now have NO identity operator, since they multiply by wedge, not composition.
#328 adds many utilities for "Functional Differential Geometry".
vector fields, in sicmutils.calculus.vector-field
:
new functions: basis-components->vector-field
,
vector-field->basis-components
vector fields now implement v/zero?
and v/zero-like
by returning
proper vector fields.
form fields, in sicmutils.calculus.vector-field
:
new functions: nform-field?
, basis-components->oneform-field
, oneform-field->basis-components
and function->oneform-field
(aliased as differential-of-function
)
Alt
, alt-wedge
provide alternate wedge product definitions
form fields now implement v/zero?
and v/zero-like
by returning proper form fields that retain their rank.
form fields now correctly multiply via *
by using sicmutils.calculus.form-field/wedge
, instead of composition.
maps between manifolds, in sicmutils.calculus.map
:
new function: pushforward-function
differential
becomes differential-of-map
, aliased back as differential
sicmutils.calculus.covariant
gains new functions: Cartan?
, Christoffel?
, Cartan->Christoffel
, symmetrize-Christoffel
, symmetrize-Cartan
, Cartan->Cartan-over-map
, geodesic-equation
, parallel-transport-equation
.
sicmutils.calculus.covariant/vector-field-Lie-derivative
can now handle structural inputs.
From #342:
Added sicmutils.calculus.derivative/D-as-matrix
and sicmutils.matrix/as-matrix
, ported from scmutils.
converted sicmutils.modint.ModInt
to a deftype
; this allows ModInt
instances to be =
to non-ModInt
numbers on the right, if the right side is equal to the residue plus any integer multiple of the modulus. v/=
gives us this behavior with numbers on the LEFT too, and ModInt
on the right.
:i
and :m
won't return the residue and modulus anymore. sicmutils.modint
gains new residue
and modulus
functions to access these attributes.The JVM version of sicmutils gains more efficient gcd
implementations for Integer
and Long
(in addition to the existing native BigInteger
gcd
), thanks to our existing Apache Commons-Math dependency.
sicmutils.structure/dual-zero
aliases compatible-zero
to match the scmutils interface. Both are now aliased into sicmutils.env
.
Structure
instances can now hold metadata (#339).
From #339:
In sicmutils.mechanics.rotation
:
gains aliases for R{xyz}
in rotate-x
, rotate-y
and rotate-z
.
R{x,y,z}-matrix
now alias rotate-{x,y,z}-matrix
.
Added new functions angle-axis->rotation-matrix
and the mysterious,
undocumented wcross->w
from scmutils
rotate-{x,y,z}-tuple
are now aliased into sicmutils.env
.
Operator
instances now ignore the right operator in operator-operator addition if the left operator passes a v/zero?
test. Contexts are still appropriately merged.
in sicmutils.simplify.rules
, the sqrt-contract
ruleset now takes a simplifier argument and attempts to use it to simplify expressions internal to a square root. As an example, if two square roots in a product simplify to the same expression, we can drop the wrapping square root; otherwise multiplication is pushed under the root as before.
simplify-square-roots
that handles roots of exponents with odd powers.sicmutils.matrix
changes:
generate
has a new 2-arity version; if you supply a single dimension the returned matrix is square.
diagonal?
returns true if its argument is a diagonal matrix, false
otherwise.
A new namespace, sicmutils.util.permute
:
factorial
moved here from sicmutils.generic
. It's still aliased into sicmutils.env
.
new functions: permutations
, combinations
, cartesian-product
, list-interchanges
, permutation-parity
, permutation-interchanges
, permute
, sort-and-permute
, subpermute
, number-of-permutations
, number-of-combinations
. See the tests for usage examples.
From #338:
(* <structure> <operator>)
multiplication pushes operator multiplication into the structure, rather than converting a structure into an operator.#337:
If you combine Operator
instances with non-equal :subtype
fields, the returned operator now keeps the parent subtype (or throws if one is not a subtype of the other).
Operator
instances now ignore any identity?
-passing operator on the left or right side of operator-operator multiplication. Contexts are still appropriately merged.
Similarly, Operator
addition ignores zero?
operators on the left or right side, and subtraction ignores zero?
operators on the right right.
#328:
Closes #249; operators now verify compatible contexts on multiplication.
Operator
instances can now provides custom zero?
, one?
, identity?
, zero-like
, one-like
and identity-like
implementations by setting a function of a single (operator-typed) argument to a keyword like :zero?
in their context. the identity operator returns true
for identity?
, and false
for one?
so that it isn't stripped by the g/*
function.
structures implement the 0-arity case of IFn now.
#335 implements g/make-rectangular
, g/make-polar
g/real-part
and g/imag-part
for clojure's Map data structure. Maps are treated as sparse vectors, any missing key on either side of make-rectangular
or make-polar
is treated as a 0 (rather than an error because the keys don't match, as in vectors).
#334 adds implementations of g/add
and the sicmutils.value.Value
protocol for clojure's Set data structure. Addition is defined as set union, and (zero-like <set>)
returns the empty set.
#334 implements g/add
, g/negate
and g/sub
for Clojure's Map data structure. Map addition is defined as a merge using g/add
on clashing values; g/sub
is the same, but any values on the right side not on the left side are negated.
Maps can also be multiplied with scalars (commutatively) or divided (scalar on the right side only) by scalars. This, plus the commutative group property declared above, mean that Clojure's maps are sparse vector spaces over anything that responds true to sicmutils.value/scalar?
... currently anything in the numeric tower up to complex, along with symbolic expressions and Differential
instances.