Skip to content

Commit 0093447

Browse files
committed
cut down readme
1 parent 63fbf4c commit 0093447

File tree

1 file changed

+20
-326
lines changed

1 file changed

+20
-326
lines changed

README.md

Lines changed: 20 additions & 326 deletions
Original file line numberDiff line numberDiff line change
@@ -1,336 +1,30 @@
1-
# SymbolicUtils.jl
2-
3-
SymbolicUtils.jl provides various utilities for symbolic computing.
1+
<h1 align="center"><a href="https://juliasymbolics.github.io/SymbolicUtils.jl/">SymbolicUtils.jl</a></h1>
42

53
[![Build Status](https://travis-ci.org/JuliaSymbolics/SymbolicUtils.jl.svg?branch=master)](https://travis-ci.com/github/JuliaSymbolics/SymbolicUtils.jl) [![Coverage Status](https://coveralls.io/repos/github/JuliaSymbolics/SymbolicUtils.jl/badge.svg?branch=master)](https://coveralls.io/github/JuliaSymbolics/SymbolicUtils.jl?branch=master)
4+
<p align="center">
5+
<a href="https://travis-ci.com/github/JuliaSymbolics/SymbolicUtils.jl">
6+
<img src="https://travis-ci.org/JuliaSymbolics/SymbolicUtils.jl.svg?branch=master"
7+
alt="Build Status (Linux)">
8+
</a>
9+
<a href="https://ci.appveyor.com/project/tlienart/Franklin-jl">
10+
<img src="https://ci.appveyor.com/api/projects/status/github/tlienart/Franklin.jl?branch=master&svg=true"
11+
alt="Build Status (Windows)">
12+
</a>
13+
<a href="https://coveralls.io/github/JuliaSymbolics/SymbolicUtils.jl?branch=master">
14+
<img src="https://coveralls.io/repos/github/JuliaSymbolics/SymbolicUtils.jl/badge.svg?branch=master"
15+
alt="Coverage">
16+
</a>
17+
</p>
618

7-
## Symbols and expressions
8-
9-
Symbols can be created using the `@syms` macro:
10-
11-
```julia
12-
julia> using SymbolicUtils
13-
14-
julia> @syms a::Integer b c d x::Real y::Number
15-
(a, b, c, d, x, y)
16-
```
17-
18-
This macro also defines the Julia variables of the same name and each is set to the its respective symbolic object.
19-
20-
The associated type `T` in the `@syms a::T` syntax, called `symtype` of the symbol, is the type the value of the symbol is supposed to be of. These types may determine the rules of symbolic simplification.
21-
22-
Arithmetic and math functions are defined on symbols and return `Term` objects which represent function call expressions.
23-
24-
Symbols can be defined to behave like functions. Both the input and output types for the function can be specified. Any application to that function will only admit either values of those types or symbols of the same `symtype`.
25-
26-
```julia
27-
julia> @syms f(x) g(x::Real, y::Real)::Real
28-
(f(::Number)::Number, g(::Real, ::Real)::Real)
29-
30-
julia> f(c)
31-
f(c)
32-
33-
julia> g(1, x)
34-
g(1, x)
35-
```
36-
37-
## Symbolic simplification
38-
39-
Use the `simplify` function to apply a built in list of rules to simplify an expression:
40-
```julia
41-
42-
julia> simplify(a + b + (x * y) + c + 2 * (x * y) + d + sin(x)^2 + cos(x)^2 - y^0)
43-
((3 * x * y) + a + b + c + d)
44-
```
45-
46-
## Pattern matching and rewriting
47-
48-
Expression rewriting rules can be created using the `@rule` macro `@rule LHS => RHS`.
49-
50-
Creates a `Rule` object. A rule object is callable, and takes an expression and rewrites
51-
it if it matches the LHS pattern to the RHS pattern, returns `nothing` otherwise.
52-
The rule language is described below.
53-
54-
LHS can be any possibly nested function call expression where any of the arugments can
55-
optionally be a Slot (`~x`) or a Segment (`~~x`) (described below).
56-
57-
If an expression matches LHS entirely, then it is rewritten to the pattern in the RHS
58-
Segment (`~x`) and slot variables (`~~x`) on the RHS will substitute the result of the
59-
matches found for these variables in the LHS.
60-
61-
**Slot**:
62-
63-
A Slot variable is written as `~x` and matches a single expression. `x` is the name of the variable. If a slot appears more than once in an LHS expression then expression matched at every such location must be equal (as shown by `isequal`).
64-
65-
_Example:_
66-
67-
Simple rule to turn any `sin` into `cos`:
68-
69-
```julia
70-
julia> @syms a b c
71-
(a, b, c)
72-
73-
julia> r = @rule sin(~x) => cos(~x)
74-
sin(~x) => cos(~x)
75-
76-
julia> r(sin(1+a))
77-
cos((1 + a))
78-
```
79-
80-
A rule with 2 segment variables
81-
82-
```julia
83-
julia> r = @rule ~x - ~y => ~x + (-(~y))
84-
~x - ~y => ~x + -(~y)
85-
86-
julia> r(a-2b)
87-
(a + (-(2 * b)))
88-
```
89-
90-
A rule that matches two of the same expressions:
91-
92-
```julia
93-
julia> r = @rule sin(~x)^2 + cos(~x)^2 => 1
94-
sin(~x) ^ 2 + cos(~x) ^ 2 => 1
95-
96-
julia> r(sin(2a)^2 + cos(2a)^2)
97-
1
98-
99-
julia> r(sin(2a)^2 + cos(a)^2)
100-
# nothing
101-
```
102-
103-
**Segment**:
104-
105-
A Segment variable is written as `~~x` and matches zero or more expressions in the
106-
function call.
107-
108-
_Example:_
109-
110-
This implements the distributive property of multiplication: `+(~~ys)` matches expressions
111-
like `a + b`, `a+b+c` and so on. On the RHS `~~ys` presents as any old julia array.
112-
113-
```julia
114-
julia> r = @rule ~x * +((~~ys)) => sum(map(y-> ~x * y, ~~ys));
115-
116-
julia> r(2 * (a+b+c))
117-
((2 * a) + (2 * b) + (2 * c))
118-
```
119-
120-
**Predicates**:
121-
122-
Predicates can be used on both `~x` and `~~x` by using the `~x::f` or `~~x::f`.
123-
Here `f` can be any julia function. In the case of a slot the function gets a single
124-
matched subexpression, in the case of segment, it gets an array of matched expressions.
125-
126-
The predicate should return `true` if the current match is acceptable, and `false`
127-
otherwise.
128-
129-
```julia
130-
julia> two_πs(x::Number) = abs(round(x/(2π)) - x/(2π)) < 10^-9
131-
two_πs (generic function with 1 method)
132-
133-
julia> two_πs(x) = false
134-
two_πs (generic function with 2 methods)
135-
136-
julia> r = @rule sin(~~x + ~y::two_πs + ~~z) => sin(+(~~x..., ~~z...))
137-
sin(~(~x) + ~(y::two_πs) + ~(~z)) => sin(+(~(~x)..., ~(~z)...))
138-
139-
julia> r(sin(a+3π))
140-
141-
julia> r(sin(a+6π))
142-
sin(a)
143-
144-
julia> r(sin(a+6π+c))
145-
sin((a + c))
146-
```
147-
148-
The predicate function gets an array of values if attached to a segment variable (`~~x`).
149-
150-
### Associative-Commutative Rules
151-
Given an expression `f(x, f(y, z, u), v, w)`, a `f` is said to be associative if the expression
152-
is equivalent to `f(x, y, z, u, v, w)` and commutative if the order of arguments does not matter.
153-
SymbolicUtils has a special `@acrule` macro meant for rules on functions which are associate
154-
and commutative such as addition and multiplication of real and complex numbers.
155-
```julia
156-
julia> @syms x y
157-
(x, y)
158-
159-
julia> acr = @acrule((~y)^(~n) * ~y => (~y)^(~n+1))
160-
ACRule((~y) ^ ~n * ~y => (~y) ^ (~n + 1))
161-
162-
julia> acr(x^2 * y * x)
163-
((x ^ 3) * y)
164-
```
165-
166-
### RuleSets
167-
168-
Rules are applied to an entire term, they do not see sub-terms
169-
```julia
170-
julia> using SymbolicUtils
171-
172-
julia> @syms x y
173-
(x, y)
174-
175-
julia> r = @rule sin(~x) => cos(~x)
176-
sin(~x) => cos(~x)
177-
178-
julia> r(sin(sin(sin(y))))
179-
cos(sin(sin(y)))
180-
```
181-
however, SymbolicUtils also defines a `RuleSet` type which stores a `Vector` of rules. `RuleSets`
182-
when applied to terms will recursively walk through the expression and apply each of it's
183-
consitituent rules until the term stops changing.
184-
```julia
185-
julia> R = RuleSet([r, @rule(~x + 1 => ~x - 1)])
186-
RuleSet(SymbolicUtils.AbstractRule[sin(~x) => cos(~x), ~x + 1 => ~x - 1])
187-
188-
julia> R(sin(sin(sin(x + 1))))
189-
cos(cos(cos((-1 + x))))
190-
```
191-
You can use the keyword argument `depth` to set a maximum number of recursions that a `RuleSet` is
192-
allowed to do
193-
```julia
194-
julia> R(sin(sin(sin(x -1))), depth=2)
195-
cos(cos(sin((x + -1))))
196-
```
197-
198-
## Interfacing with SymbolicUtils.jl
199-
200-
This section is for Julia package developers who may want to use the `simplify` and rule rewriting system on their own expression types.
201-
202-
Our intention is for SymbolicUtils to be useful even for packages with their own custom symbolic types which
203-
differ from those offered by SymbolicUtils. To this end, SymbolicUtils provides an interface to convert expression
204-
tree types which have
205-
* an `operation`, (i.e. function to apply)
206-
* `arguments` which the `operation` is applied to
207-
* `variable` types which are the atoms from which the expression tree is built
208-
* optionally, a type which should `typeof(operation(arguments...))` should return if it were to be run.
209-
210-
SymbolicUtils uses a function `to_symbolic` to convert aribtrarty types to it's own internal types.
211-
212-
The following methods should be defined for an expression tree type `T` with symbol types `S` to work
213-
with SymbolicUtils.jl
214-
215-
#### `istree(x::T)`
216-
217-
Check if `x` represents an expression tree. If returns true,
218-
it will be assumed that `operation(::T)` and `arguments(::T)`
219-
methods are defined. Definining these three should allow use
220-
of `simplify` on custom types. Optionally `symtype(x)` can be
221-
defined to return the expected type of the symbolic expression.
222-
223-
#### `operation(x::T)`
224-
225-
Returns the operation (a function object) performed by an expression
226-
tree. Called only if `istree(::T)` is true. Part of the API required
227-
for `simplify` to work. Other required methods are `arguments` and `istree`
228-
229-
#### `arguments(x::T)`
230-
231-
Returns the arguments (a `Vector`) for an expression tree.
232-
Called only if `istree(x)` is `true`. Part of the API required
233-
for `simplify` to work. Other required methods are `operation` and `istree`
234-
235-
#### `to_symbolic(x::S)`
236-
Convert your variable type to a `SymbolicUtils.Sym`. Suppose you have
237-
```julia
238-
struct MySymbol
239-
s::Symbol
240-
end
241-
```
242-
which could represent any type symbolically, then you would define
243-
```julia
244-
SymbolicUtils.to_symbolic(s::MySymbol) = SymbolicUtils.Sym(s.s)
245-
```
246-
247-
### Optional
248-
249-
#### `symtype(x)`
250-
251-
The supposed type of values in the domain of x. Tracing tools can use this type to
252-
pick the right method to run or analyse code.
253-
254-
This defaults to `typeof(x)` if `x` is numeric, or `Any` otherwise.
255-
For the types defined in this package, namely `T<:Symbolic{S}` it is `S`.
256-
257-
Define this for your symbolic types if you want `simplify` to apply rules
258-
specific to numbers (such as commutativity of multiplication). Or such
259-
rules that may be implemented in the future.
260-
261-
#### `promote_symtype(f, arg_symtypes...)`
262-
263-
Returns the appropriate output type of applying `f` on arguments of type `arg_symtypes`.
264-
265-
### Example
266-
267-
Suppose you were feeling the temptations of type piracy and wanted to make a quick and dirty
268-
symbolic library built on top of Julia's `Expr` type, e.g.
269-
270-
```julia
271-
for f [:+, :-, :*, :/, :^] #Note, this is type piracy!
272-
@eval begin
273-
Base.$f(x::Union{Expr, Symbol}, y::Number) = Expr(:call, $f, x, y)
274-
Base.$f(x::Number, y::Union{Expr, Symbol}) = Expr(:call, $f, x, y)
275-
Base.$f(x::Union{Expr, Symbol}, y::Union{Expr, Symbol}) = (Expr(:call, $f, x, y))
276-
end
277-
end
278-
279-
280-
julia> ex = 1 + (:x - 2)
281-
:((+)(1, (-)(x, 2)))
282-
```
283-
How can we use SymbolicUtils.jl to convert `ex` to `(-)(:x, 1)`? We simply implement `istree`,
284-
`operation`, `arguments` and `to_symbolic` and we'll be off to the races:
285-
```julia
286-
using SymbolicUtils: Sym, istree, operation, arguments, to_symbolic
287-
288-
SymbolicUtils.istree(ex::Expr) = ex.head == :call
289-
SymbolicUtils.operation(ex::Expr) = ex.args[1]
290-
SymbolicUtils.arguments(ex::Expr) = ex.args[2:end]
291-
SymbolicUtils.to_symbolic(s::Symbol) = Sym(s)
292-
293-
julia> simplify(ex)
294-
(-1 + x)
295-
296-
julia> dump(simplify(ex))
297-
Term{Any}
298-
f: + (function of type typeof(+))
299-
arguments: Array{Any}((2,))
300-
1: Int64 -1
301-
2: Sym{Any}
302-
name: Symbol x
303-
```
304-
this thing returns a `Term{Any}`, but it's not hard to convert back to `Expr`:
305-
```julia
306-
to_expr(t::Term) = Expr(:call, operation(t), to_expr.(arguments(t))...)
307-
to_expr(x) = x
19+
SymbolicUtils.jl provides various utilities for symbolic computing.
30820

309-
julia> to_expr(simplify(ex))
310-
:((+)(-1, x))
21+
[![Build Status](https://travis-ci.org/JuliaSymbolics/SymbolicUtils.jl.svg?branch=master)](https://travis-ci.com/github/JuliaSymbolics/SymbolicUtils.jl) [![Coverage Status](https://coveralls.io/repos/github/JuliaSymbolics/SymbolicUtils.jl/badge.svg?branch=master)](https://coveralls.io/github/JuliaSymbolics/SymbolicUtils.jl?branch=master)
31122

312-
julia> dump(ans)
313-
Expr
314-
head: Symbol call
315-
args: Array{Any}((3,))
316-
1: + (function of type typeof(+))
317-
2: Int64 -1
318-
3: Symbol x
319-
```
23+
[Symbols in SymbolicUtils](https://juliasymbolics.github.io/SymbolicUtils.jl/#creating_symbolic_expressions) carry type information. Operations on them propagate this information. [A rule-based rewriting language](https://juliasymbolics.github.io/SymbolicUtils.jl/#rule-based_rewriting) can be used to find subexpressions that satisfy arbitrary conditions and apply arbitrary transformations on the matches. The library also contains a set of useful [simplification](https://juliasymbolics.github.io/SymbolicUtils.jl/#simplification) rules for expressions of numeric symbols and numbers. These can be remixed and extended for special purposes.
32024

321-
Now suppose we actaully wanted all `Symbol`s to be treated as `Real` numbers. We can simply define
322-
```julia
323-
SymbolicUtils.symtype(s::Symbol) = Real
25+
If you are a Julia package develper in need of a rule rewriting system for your own types, have a look at the [interfacing guide](https://juliasymbolics.github.io/SymbolicUtils.jl/interface/).
32426

325-
julia> dump(simplify(ex))
326-
Term{Real}
327-
f: + (function of type typeof(+))
328-
arguments: Array{Any}((2,))
329-
1: Int64 -1
330-
2: Sym{Real}
331-
name: Symbol x
332-
```
333-
and now all our analysis is able to figure out that the `Term`s are `Number`s.
27+
[**Go to the manual**](https://juliasymbolics.github.io/SymbolicUtils.jl/)
33428

33529
# Citations
33630

0 commit comments

Comments
 (0)