-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
456 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) <2013> <j verzani> | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
## Package to bring `sympy` functionality into `julia` via `PyCall` | ||
|
||
The `SymPy` package (`http://sympy.org/`) is a Python library for symbolic mathematics. | ||
|
||
With the `PyCall` package of `julia`, one has access to the many features of `SymPy`. | ||
|
||
This `SymPy` package provides a light interface for some of the features of `SymPy` that makes working with `SymPy` objects a bit easier. | ||
|
||
To use it, both `Python` and the `SymPy` package must be installed on your system. | ||
|
||
|
||
## The `PyCall` interface to `SymPy` | ||
|
||
Using `PyCall` to access `SymPy` is somewhat cumbersome. The following is how one would define a symbolic value `x`, take its sine, then evaluate at `pi`, say: | ||
|
||
``` | ||
using PyCall | ||
@pyimport sympy | ||
x = sympy[:Symbol]("x") | ||
y = sympy[:sin](x) | ||
y[:subs](x, pi) | u -> convert(Real, u) | ||
``` | ||
|
||
The `symbol` and `sin` methods of the `sympy` object are used in the first two lines. The use of `[:symbol]` replaces the dot notation, `sympy.symbol` of `Python`. The `subs` method of the `y` object is called similarly, but with a the `PyObject` instance `y`. We convert this into a `Real` number from the `PyObject` value returned by the `:subs` method. | ||
|
||
|
||
Even more cumbersome is the simple task of finding `2x`. As this multiplication is done at the python level and is not a method of `sympy` or the `x` object, we need to evaluate python code. Here is one solution: | ||
|
||
``` | ||
x = sympy[:Symbol]("x") | ||
pyeval("k*x", {:k=>2, :x=>x}) | ||
``` | ||
|
||
This gets replaced by a more natural syntax: | ||
|
||
``` | ||
using SymPy | ||
x = sym"x" # or Sym("x") or Sym(:x) | ||
y = sin(x) | ||
subs(y, x, pi) | ||
``` | ||
|
||
The object `x` we create is of type `Sym`, a simple proxy for the underlying `PyObject`. We then overload the familiar math functions so that working with symbolic expressions can use natural `julia` language. For example, to find `2x` we just use: | ||
|
||
``` | ||
x = sym"x" | ||
y = 2x | ||
``` | ||
|
||
The `PyCall` interface is needed for serious work as only a small portion of the `SymPy` interface is exposed. To dig the `PyObject` out of a `Sym` object, you access its property `x`, as in `y.x`. This is necessary if passing a `Sym` object to a method call. | ||
|
||
## Examples | ||
|
||
To make a symbolic object (of type `Sym`) we have the `Sym` constructor and the convenient `sym` macro: | ||
|
||
``` | ||
x = Sym("x") | ||
h, y = Sym("h", :y) | ||
``` | ||
|
||
Operator overloading of the basic math functions allows symbolic expressions to be combined without fuss: | ||
|
||
``` | ||
1/x + 1/x^2 + x # pretty prints x + 1/x + 1/x^2 | ||
``` | ||
|
||
|
||
The `together` functions combines terms: | ||
|
||
``` | ||
together(1/x + 1/x^2 + x) # (x^3 + x + 1) / x^2 | ||
``` | ||
|
||
The `expand` function breaks them up; | ||
|
||
``` | ||
expand( (x + 1)*(x+2)) # x^2 + 3 * x + 2 | ||
``` | ||
|
||
The `apart` function does partial fraction decomposition: | ||
|
||
``` | ||
apart(1/(x +2)/(x + 1)) # -1/(x+2) + 1/(x+1) | ||
``` | ||
|
||
|
||
The `subs` command is used to substitute values. These values are typically numeric, though they may be other symbols: | ||
|
||
``` | ||
subs(x + y, x, 3) # y + 3 | ||
subs(x*y, y, 24 - 2x) # x⋅(-2⋅x + 24) | ||
``` | ||
|
||
### Plotting | ||
|
||
Plotting is done with the `GoogleCharts` package. This is temporary while other plotting interfaces stabilize. We can plot expressions or tuples of expressions: | ||
|
||
``` | ||
plot(exp(-x) * sin(x), 0, 2pi) # opens plot in browser | ||
plot( (sin(x), diff(sin(x), x) ), 0, 2pi) | ||
### Calculus | ||
The `limit` function computes simple limits: | ||
``` | ||
limit(sin(x)/x, x, 0) # 0 | ||
limit(sin(y*x)/x, x, 0) # y | ||
limit(sin(y*x)/x, y, 0) # 0 | ||
``` | ||
One can take limits at infinity using `oo` (but not `Inf`): | ||
``` | ||
limit(sin(x)/x, x, Inf) # ERRORS! | ||
limit(sin(x)/x, x, oo) # 0 | ||
``` | ||
Derivatives, higher-order derivative and partial derivatives are computed by `diff`. | ||
``` | ||
diff(sin(x*y), x) # y⋅cos(x⋅y) (first derivative, y as constant) | ||
diff(sin(x*y), x, 2) # -y^2 * sin(x⋅y) (second derivative in x) | ||
diff(sin(x*y), x, y) # -x * y * sin(x * y) + cos(x * y) (mixed partials) | ||
``` | ||
Integration is done through `integrate`. Both definite and indefinite integrals are possible: | ||
``` | ||
integrate(x^2, x) # x^3/3 (no constant term) | ||
integrate(x^2, x, 0, 1) # 1/3 (catching up to Archimedes) | ||
``` | ||
One can iterate integrations to do double integrals via Fubini: | ||
``` | ||
integrate(integrate(x*y, x, 0, 1), y, 0, 1) # 1/4 | ||
``` | ||
The calling pattern above is actually a convenience not provided by `SymPy` which uses a tuple to specify the variable to integrate over and the limits: | ||
``` | ||
integrate(x^2, (x, 0, 1)) # 1/3 | ||
``` | ||
For simple integrals this is an extra pair of parentheses, but for multiple integrals is it more convenient: | ||
``` | ||
integrate(x*y, (x, 0, 1), (y, 0, 1)) # still 1/4 | ||
``` | ||
As well, the inner limits can be expressed using outer variables: | ||
``` | ||
integrate(x*y, (x, 0, y), (y, 0,1)) # 1/8 | ||
``` | ||
Summations can be done through the `summation` function: | ||
``` | ||
summation(1/x, (x, 1, 10)) # 7381 / 2520 | ||
summation(1/x, (x, 1, oo)) # zoo | ||
summation(1/x^2, (x, 1, oo)) # pi^2/6 | ||
``` | ||
Taylor Series can be found through the `series` function | ||
``` | ||
series(cos(x), x, 0, 3) # 1 - x^2/2 + O(x^3) (around 0, of order 3) | ||
``` | ||
These could also be generated through the `diff` function: | ||
``` | ||
[diff(cos(y), y, i)/factorial(i)*x^i for i in 0:3] | sum | u -> subs(u, y, 0) | ||
``` | ||
The `solve` function can solve equations. | ||
``` | ||
solve(x^2 -2, x) # an Any array of PyObject's | ||
``` | ||
The output is not simplified. In this case, we can apply `convert` to convert the values to `Real`: | ||
``` | ||
[convert(Real, u) for u in solve(x^2 -2, x)] | ||
``` | ||
Differential equations can be solved with `dsolve`. Here we solve $f'(x) + f(x) = 0$. To do so, we need to create a `Function` object. As that keyword is reserved, we call the constructor `SymFunction`: | ||
``` | ||
f = SymFunction("f") | ||
eq = diff(f(x), x) + f(x) | ||
dsolve(eq, f(x)) # c1 * exp(-x) as a function object | ||
``` | ||
Solving $f''(x) + f(x) = 0$ is similar, we just take a second derivative | ||
``` | ||
eq = diff(f(x), x, 2) + f(x) | ||
dsolve(eq, f(x)) # c1 * sin(x) + c2 * cos(x) | ||
``` | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
PyCall | ||
GoogleCharts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
module SymPy | ||
|
||
using GoogleCharts | ||
using PyCall | ||
@pyimport sympy | ||
|
||
|
||
import Base.getindex | ||
import Base.show | ||
import Base.convert | ||
import Base.sin, Base.cos, Base.tan, Base.sinh, Base.cosh, Base.tanh, Base.asin, Base.acos, | ||
Base.atan, Base.asinh, Base.acosh, Base.atanh, Base.sec, Base.csc, Base.cot, Base.asec, | ||
Base.acsc, Base.acot, Base.sech, Base.csch, Base.coth, Base.asech, Base.acsch, Base.acoth, | ||
Base.sinc, Base.cosc, Base.cosd, Base.cotd, Base.cscd, Base.secd, Base.sind, Base.tand, | ||
Base.acosd, Base.acotd, Base.acscd, Base.asecd, Base.asind, Base.atand, Base.atan2, | ||
Base.radians2degrees, Base.degrees2radians, Base.log, Base.log2, | ||
Base.log10, Base.log1p, Base.exponent, Base.exp, Base.exp2, Base.expm1, Base.cbrt, Base.sqrt, | ||
Base.square, Base.erf, Base.erfc, Base.erfcx, Base.erfi, Base.dawson, Base.ceil, Base.floor, | ||
Base.trunc, Base.round, Base.significand | ||
import Base.factorial, Base.gamma, Base.beta | ||
import Base.solve | ||
|
||
export sympy | ||
export Sym, @sym_str | ||
export pprint, latex | ||
export SymFunction, SymMatrix, | ||
n, subs, | ||
expand, together, apart, | ||
limit, diff, series, integrate, summation, | ||
I, oo, | ||
Ylm, assoc_legendre, chebyshevt, legendre, hermite, | ||
dsolve, | ||
plot, | ||
poly, nroots, real_roots | ||
export members | ||
|
||
|
||
|
||
include("utils.jl") | ||
include("math.jl") | ||
include("plot.jl") | ||
|
||
end |
Oops, something went wrong.