This namespace contains many sets of algebraic simplification rules you can use to build simplifiers for algebraic structures.
[[rules]] currently holds a mix of:
associative
and constant-elimination
designed to help you build lightweight custom
term-rewriting simplifiers.NOTE: Expect this namespace to be broken out into more fine-grained namespaces. There are TODO entries throughout the docstrings left as tips for how to proceed here.
This namespace contains many sets of algebraic simplification rules you can use to build simplifiers for algebraic structures. [[rules]] currently holds a mix of: - rulesets ported from the scmutils library - more fine-grained, tuneable rulesets like [[associative]] and [[constant-elimination]] designed to help you build lightweight custom term-rewriting simplifiers. NOTE: Expect this namespace to be broken out into more fine-grained namespaces. There are TODO entries throughout the docstrings left as tips for how to proceed here.
When true
, allows:
(atan y x) => (atan (/ y d) (/ x d))
where d=(gcd x y)
.
This is fine if d
is a number (Numeric gcd
is always positive), but may lose
quadrant information if d
is a symbolic expression that can be negative for
some values of its variables.
When `true`, allows: ``` (atan y x) => (atan (/ y d) (/ x d)) ``` where `d=(gcd x y)`. This is fine if `d` is a number (Numeric `gcd` is always positive), but may lose quadrant information if `d` is a symbolic expression that can be negative for some values of its variables.
When true, allows commutation of partial derivatives so that partial derivatives appear in order.
For example:
(((* (partial 2 1) (partial 1 1)) FF) (up t (up x y) (down p_x p_y)))
Since the partial indices in the outer derivative are lexically greater than those of the inner, we canonicalize by swapping the order:
(((* (partial 1 1) (partial 2 1)) FF) (up t (up x y) (down p_x p_y)))
When the components selected by the partials are unstructured (e.g. real), this is okay due to the 'equality of mixed partials'.
When true, allows commutation of partial derivatives so that partial derivatives appear in order. For example: ```clojure (((* (partial 2 1) (partial 1 1)) FF) (up t (up x y) (down p_x p_y))) ``` Since the partial indices in the outer derivative are lexically greater than those of the inner, we canonicalize by swapping the order: ```clojure (((* (partial 1 1) (partial 2 1)) FF) (up t (up x y) (down p_x p_y))) ``` When the components selected by the partials are unstructured (e.g. real), this is okay due to the 'equality of mixed partials'.
When true
, allows division through the numerator by numbers in the
denominator:
(/ (+ (* 4 x) 5) 3) => (+ (* 4/3 x) 5/3)
This setting is true
by default.
When `true`, allows division through the numerator by numbers in the denominator: ``` (/ (+ (* 4 x) 5) 3) => (+ (* 4/3 x) 5/3) ``` This setting is `true` by default.
Allows (x^a)^b => x^(a*b)
.
This is dangerous, because a root can be gained or lost:
x = (x^(1/2))^2 != ((x^2)^1/2)=+-x
Allows `(x^a)^b => x^(a*b)`. This is dangerous, because a root can be gained or lost: ``` x = (x^(1/2))^2 != ((x^2)^1/2)=+-x ```
Traditionally, sqrt(x)
is the positive square root, but x^(1/2)
is both
positive and negative roots.
Setting *expt-half->sqrt?*
to true
maps x^(1/2)
to sqrt(x)
,
potentially losing a root.
Traditionally, `sqrt(x)` is the positive square root, but `x^(1/2)` is both positive and negative roots. Setting [[*expt-half->sqrt?*]] to `true` maps `x^(1/2)` to `sqrt(x)`, potentially losing a root.
When true
, enables the half-angle reductions described in half-angle
.
Note from GJS: 'Sign of result is hairy!'
When `true`, enables the half-angle reductions described in [[half-angle]]. Note from GJS: 'Sign of result is hairy!'
When true
, allows trigonometric inverse functions to simplify:
(asin (sin x)) => x
Because trigonometric functions like sin
and cos
are cyclic, this can lose
multi-value info (as with [[log-exp-simplify]]).
When `true`, allows trigonometric inverse functions to simplify: ``` (asin (sin x)) => x ``` Because trigonometric functions like `sin` and `cos` are cyclic, this can lose multi-value info (as with [[*log-exp-simplify*]]).
If true, allows the following simplification to proceed:
(log (exp x)) => x.
Because exp(i*x) == exp(i*(x+n*2pi))
for all integral n
, this setting can
confuse x
with x+n*2pi
.
If true, allows the following simplification to proceed: ```clojure (log (exp x)) => x. ``` Because `exp(i*x) == exp(i*(x+n*2pi))` for all integral `n`, this setting can confuse `x` with `x+n*2pi`.
When true
, allows arguments of sin
, cos
and tan
that are
rational multiples of 'pi
to be reduced. See trig:special
for these
rules.
When `true`, allows arguments of `sin`, `cos` and `tan` that are rational multiples of `'pi` to be reduced. See [[trig:special]] for these rules.
If x is real, then (sqrt (square x)) = (abs x)
.
Setting *sqrt-expt-simplify?*
to true
allows (sqrt (square x)) = x
,
potentially causing a problem if x
is in fact negative.
If x is real, then `(sqrt (square x)) = (abs x)`. Setting [[*sqrt-expt-simplify?*]] to `true` allows `(sqrt (square x)) = x`, potentially causing a problem if `x` is in fact negative.
If x
and y
are real and non-negative, then
(* (sqrt x) (sqrt y)) = (sqrt (* x y))
This is not true for negative factors. Setting *sqrt-factor-simplify?*
to
true enables this simplification, causing a problem if x
or y
are in fact
negative.
If `x` and `y` are real and non-negative, then ``` (* (sqrt x) (sqrt y)) = (sqrt (* x y)) ``` This is not true for negative factors. Setting [[*sqrt-factor-simplify?*]] to true enables this simplification, causing a problem if `x` or `y` are in fact negative.
Transforms products of trig functions into functions of sums of angles.
For example:
(* (sin x) (cos y))
;;=>
(+ (* 1/2 (sin (+ x y)))
(* 1/2 (sin (+ x (* -1 y)))) )
Transforms products of trig functions into functions of sums of angles. For example: ``` (* (sin x) (cos y)) ;;=> (+ (* 1/2 (sin (+ x y))) (* 1/2 (sin (+ x (* -1 y)))) ) ```
sin
is odd, and cos
is even. we canonicalize by moving the sign out of the
first term of the argument.
`sin` is odd, and `cos` is even. we canonicalize by moving the sign out of the first term of the argument.
(associative & ops)
Takes any number of operator symbols ops
like '+
, '*
and returns a rule
that collapses nested applications of each operation into a single
sequence. (The associative property lets us strip parentheses.)
(let [rule (associative '+ '*)
f (rule-simplifier rule)]
(= (+ x y z a (* b c d) cake face)
(f '(+ x (+ y (+ z a) (* b (* c d))
(+ cake face))))))
Takes any number of operator symbols `ops` like `'+`, `'*` and returns a rule that collapses nested applications of each operation into a single sequence. (The associative property lets us strip parentheses.) ```clojure (let [rule (associative '+ '*) f (rule-simplifier rule)] (= (+ x y z a (* b c d) cake face) (f '(+ x (+ y (+ z a) (* b (* c d)) (+ cake face)))))) ```
(commutative & ops)
Takes any number of operator symbols ops
like '+
, '*
and returns a rule
that sorts the argument list of any multiple-arity call to any of the supplied
operators. Sorting is accomplished with emmy.expression/sort
.
For example:
(let [rule (commutative '* '+)]
(= '(* 2 3 a b c (+ c a b))
(rule '(* c a b (+ c a b) 3 2))))
Takes any number of operator symbols `ops` like `'+`, `'*` and returns a rule that sorts the argument list of any multiple-arity call to any of the supplied operators. Sorting is accomplished with [[emmy.expression/sort]]. For example: ```clojure (let [rule (commutative '* '+)] (= '(* 2 3 a b c (+ c a b)) (rule '(* c a b (+ c a b) 3 2)))) ```
(constant-elimination op constant)
Takes an operator symbol op
and an identity element constant
and returns a
rule that eliminates instances of constant
inside any-arity forms like
(<op> ,,,args,,,)
Takes an operator symbol `op` and an identity element `constant` and returns a rule that eliminates instances of `constant` inside any-arity forms like ```clojure (<op> ,,,args,,,) ```
(constant-promotion op constant)
Takes an operator symbol op
and an identity element constant
and returns a
rule that turns binary forms with constant
on either side into constant
.
This rule is useful for commutative annihilators like:
(* 0 <anything>) => 0
(and false <anything>) => false
(or true <anything>) => true
Takes an operator symbol `op` and an identity element `constant` and returns a rule that turns binary forms with `constant` on either side into `constant`. This rule is useful for commutative annihilators like: ```clojure (* 0 <anything>) => 0 (and false <anything>) => false (or true <anything>) => true ```
Set of rules that collect adjacent products, exponents and nested exponents into exponent terms.
Set of rules that collect adjacent products, exponents and nested exponents into exponent terms.
(idempotent & ops)
Returns a simplifier that will remove consecutive duplicate arguments to any
of the operations supplied as ops
. Acts as identity otherwise.
(let [rule (idempotent 'and)]
(= '(and a b c d)
(rule '(and a b b c c c d))))
Returns a simplifier that will remove consecutive duplicate arguments to any of the operations supplied as `ops`. Acts as identity otherwise. ```clojure (let [rule (idempotent 'and)] (= '(and a b c d) (rule '(and a b b c c c d)))) ```
(logexp simplify)
Returns a rule simplifier that attempts to simplify nested exp and log forms.
You can tune the behavior of this simplifier with *log-exp-simplify?*
and *sqrt-expt-simplify?*
.
NOTE: logexp
returns a rule-simplifier
, which memoizes its traversal
through the supplied expression. This means that if you try to
customize logexp
with dynamic binding variables AFTER passing an
expression into it, you may get a memoized result which used the previous
dynamic binding.
This is a problem we should address!
Returns a rule simplifier that attempts to simplify nested exp and log forms. You can tune the behavior of this simplifier with [[*log-exp-simplify?*]] and [[*sqrt-expt-simplify?*]]. NOTE: [[logexp]] returns a `rule-simplifier`, which memoizes its traversal through the supplied expression. This means that if you try to customize [[logexp]] with dynamic binding variables AFTER passing an expression into it, you may get a memoized result which used the previous dynamic binding. This is a problem we should address!
Rule simplifier for forms that contain magnitude
entries.
Rule simplifier for forms that contain `magnitude` entries.
(miscsimp simplify)
Simplifications for various exponent forms (assuming commutative multiplication).
NOTE that we have some similarities to exponent-contract
above - that
function works for non-commutative multiplication - AND that this needs a new
name.
Simplifications for various exponent forms (assuming commutative multiplication). NOTE that we have some similarities to [[exponent-contract]] above - that function works for non-commutative multiplication - AND that this needs a new name.
(non-negative-factors! x id)
(non-negative-factors! x y id)
Takes one or two simplified expressions x
and y
and a symbolic identifier
id
and registers an assumption that both sides are non-negative.
Returns the conjuction of both assumptions in the two argument case, or the single assumption in the one-argument case.
Takes one or two simplified expressions `x` and `y` and a symbolic identifier `id` and registers an assumption that both sides are non-negative. Returns the conjuction of both assumptions in the two argument case, or the single assumption in the one-argument case.
(sqrt-expand simplify)
Returns a rule simplifier that distributes the radical sign across products and
quotients. The companion rule sqrt-contract
reassembles what remains.
NOTE that doing this may allow equal subexpressions within the radicals to cancel in various ways.
Turn this simplifier on and off with *sqrt-factor-simplify?*
.
Returns a rule simplifier that distributes the radical sign across products and quotients. The companion rule [[sqrt-contract]] reassembles what remains. NOTE that doing this may allow equal subexpressions within the radicals to cancel in various ways. Turn this simplifier on and off with [[*sqrt-factor-simplify?*]].
(trig:special simplify)
TODO consolidate the symbolic checkers here with the constructor
simplifications in trig:special
.
TODO consolidate the symbolic checkers here with the constructor simplifications in [[trig:special]].
(unary-elimination & ops)
Takes a sequence ops
of operator symbols like '+
, '*
and returns a rule
that strips these operations off of unary applications.
(let [rule (unary-elimination '+ '*)
f (rule-simplifier rule)]
(f '(+ x y (* z) (+ a))))
;;=> (+ x y z a)
Takes a sequence `ops` of operator symbols like `'+`, `'*` and returns a rule that strips these operations off of unary applications. ```clojure (let [rule (unary-elimination '+ '*) f (rule-simplifier rule)] (f '(+ x y (* z) (+ a)))) ;;=> (+ x y z a) ```
(universal-reductions simplify)
Returns a rule simplifier of rules that are almost always helpful.
Returns a rule simplifier of rules that are almost always helpful.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close