Skip to content

Commit 0ce7fe4

Browse files
committed
doc edits
1 parent 2d18a1a commit 0ce7fe4

File tree

2 files changed

+39
-73
lines changed

2 files changed

+39
-73
lines changed

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,23 @@ There would be a few deprecations:
1717

1818
* `elements` for sets would be removed (convert to a `Set` by default)
1919

20-
* `sympy.poly` *not* `sympy.Poly`, though `sympy.Poly` does work for now via a hacky thing to manage `ManagedProperties`,
20+
* `sympy.poly` *not* `sympy.Poly`
2121

2222
* `limit(ex, x, c)` deprecated; use `limit(ex, x=>c)` or `sympy.limit`
2323

24-
* `Base.show` isn't *currently* using pretty priting
24+
* `Base.show` isn't *currently* using pretty printing
2525

2626
* Would `Q` be ported? (Use `\itQ` for now)
2727

28-
* What to do with matrices? Using `Matrix{Sym}` with no `SymMatrix` type expected
29-
30-
* would we export `CommonEq` symbols?
28+
* What to do with matrices? Using `Matrix{Sym}` with no `SymMatrix` type expected. Views seem off, so for now a copy is made.
3129

3230
* no new special functions exported, just the ones in SpecialFunctions.jl
3331

3432

3533
## Installing `sympy`,
3634

37-
To install `sympy` in `PythonCall` isn't hard; below shows how it may be done. If this were to become registered, automating this would be very desirable.
35+
The `sympy` package for Python should install with the package through `PythonCall` and `CondaPkg`. If not,
36+
to install `sympy` in `PythonCall` isn't hard; below shows how it may be done.
3837

3938
```
4039
using PythonCall

docs/src/introduction.md

Lines changed: 34 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ It owes an enormous debt to the tutorial for using SymPy within Python which may
2020
[here](http://docs.sympy.org/dev/tutorial/index.html). The overall structure and many examples are taken from that work, with adjustments and additions to illustrate the differences due to using `SymPy` within `Julia`.
2121

2222

23-
After installing `SymPy`, which is discussed in the package's `README`
24-
file, we must first load it into `Julia` with the standard command
23+
After installing `SymPyCall` we must first load it into `Julia` with the standard command
2524
`using`:
2625

2726

@@ -91,7 +90,7 @@ The `@syms` macro is recommended, and will be modeled in the following, as it ma
9190

9291
### Assumptions
9392

94-
Finally, there is the `symbols` constructor for producing symbolic objects. With `symbols` it is
93+
Finally, there is the `symbols` constructor for producing symbolic objects. With `symbols` (and with `@syms`) it is
9594
possible to pass assumptions onto the variables. A list of possible
9695
assumptions is
9796
[here](http://docs.sympy.org/dev/modules/core.html#module-sympy.core.assumptions). Some
@@ -155,16 +154,14 @@ use `Sym` to create a variable from a function name in Base.
155154

156155
### Special constants
157156

158-
`Julia` has its math constants, like `pi` and `e`, `SymPy` as well. A few of these have `Julia` counterparts provided by `SymPy`. For example, these two constants are defined (where `oo` is for infinity):
157+
`Julia` has its math constants, like `pi` and `e`, `SymPy` as well. A few of these have `Julia` counterparts provided by `SymPyCall`. For example, these two constants are defined (where `oo` is for infinity):
159158

160159
```jldoctest introduction
161160
julia> PI, oo
162161
(pi, oo)
163162
164163
```
165164

166-
(The pretty printing of SymPy objects does not work for tuples.)
167-
168165
Numeric values themselves can be symbolic. This example shows the
169166
difference. The first `asin` call dispatches to `Julia`'s `asin`
170167
function, the second to `SymPy`'s:
@@ -221,7 +218,7 @@ z + 1 + pi
221218

222219
!!! note
223220

224-
The calling pattern for `subs` is different from a typical `Julia` function call. The `subs` call is `object.method(arguments)` whereas a more "`Julia`n" function call is `method(objects, other objects....)`, as `Julia` offers multiple dispatch of methods. `SymPy` uses the Python calling method, adding in `Julia`n style when appropriate for generic usage within `Julia`. `SymPy` imports most all generic functions from the underlying `sympy` module and specializes them on a symbolic first argument.
221+
The calling pattern for `subs` is different from a typical `Julia` function call. The `subs` call is `object.method(arguments)` whereas a more "`Julia`n" function call is `method(objects, other objects....)`, as `Julia` offers multiple dispatch of methods. `SymPy` uses the Python calling method, adding in `Julia`n style when appropriate for generic usage within `Julia`. `SymPyCall` imports many generic functions from the underlying `sympy` module and specializes them on a symbolic first argument.
225222

226223
For `subs`, the simple substitution `ex.object(x,a)` is similar to simple function evaluation, so `Julia`'s call notation will work. To specify the pairing off of `x` and `a`, the `=>` pairs notation is used.
227224

@@ -287,9 +284,9 @@ necessary at times if `N` does not give the desired type.
287284

288285
## Algebraic expressions
289286

290-
`SymPy` overloads many of `Julia`'s functions to work with symbolic objects, such as seen above with `asin`. The usual mathematical operations such as `+`, `*`, `-`, `/` etc. work through `Julia`'s promotion mechanism, where numbers are promoted to symbolic objects, others dispatch internally to related `SymPy` functions.
287+
`SymPyCall` overloads many of `Julia`'s functions to work with symbolic objects, such as seen above with `asin`. The usual mathematical operations such as `+`, `*`, `-`, `/` etc. work through `Julia`'s promotion mechanism, where numbers are promoted to symbolic objects, others dispatch internally to related SymPy functions.
291288

292-
In most all cases, thinking about this distinction between numbers and symbolic numbers is unnecessary, as numeric values passed to `SymPy` functions are typically promoted to symbolic expressions. This conversion will take math constants to their corresponding `SymPy` counterpart, rational expressions to rational expressions, and floating point values to floating point values. However there are edge cases. An expression like `1//2 * pi * x` will differ from the seemingly identical `1//2 * (pi * x)`. The former will produce a floating point value from `1//2 * pi` before being promoted to a symbolic instance. Using the symbolic value `PI` makes this expression work either way.
289+
In most all cases, thinking about this distinction between numbers and symbolic numbers is unnecessary, as numeric values passed to `SymPyCall` functions are typically promoted to symbolic expressions. This conversion will take math constants to their corresponding `SymPyCall` counterpart, rational expressions to rational expressions, and floating point values to floating point values. However there are edge cases. An expression like `1//2 * pi * x` will differ from the seemingly identical `1//2 * (pi * x)`. The former will produce a floating point value from `1//2 * pi` before being promoted to a symbolic instance. Using the symbolic value `PI` makes this expression work either way.
293290

294291
Most of `Julia`'s
295292
[mathematical](http://julia.readthedocs.org/en/latest/manual/mathematical-operations/#elementary-functions)
@@ -301,7 +298,7 @@ expected, as the former call first dispatches to a generic defintion,
301298
but the latter two expressions do not.
302299

303300

304-
`SymPy` makes it very easy to work with polynomial and rational expressions. First we create some variables:
301+
`SymPyCall` makes it very easy to work with polynomial and rational expressions. First we create some variables:
305302

306303
```jldoctest introduction
307304
julia> @syms x y z
@@ -366,7 +363,7 @@ x*y^2 + x + y*(x^2 + x)
366363

367364
These are identical expressions, though viewed differently.
368365

369-
A more broad-brush approach is to let `SymPy` simplify the values. In this case, the common value of `x` is factored out:
366+
A more broad-brush approach is to let `SymPyCall` simplify the values. In this case, the common value of `x` is factored out:
370367

371368
```jldoctest introduction
372369
julia> simplify(q)
@@ -613,7 +610,7 @@ julia> q.coeffs()
613610

614611
!!! note
615612

616-
XXX This is SYmPy not SymPyCall Either `sympy.poly` or `sympy.Poly` may be used. The `Poly` constructor from SymPy is *not* a function, so is not exported when `SymPy` is loaded. To access it, the object must be qualified by its containing module, in this case `Poly`. Were it to be used frequently, an alias could be used, as in `const Poly=sympy.Poly` *or* the `import_from` function, as in `import_from(sympy, :Poly)`. The latter has some attempt to avoid naming collisions.
613+
This is `sympy` not `SymPyCall`. Using `sympy.Poly` is not supported. The `Poly` constructor from SymPy is *not* a function, so is not exported when `SymPyCa;;` is loaded.
617614

618615

619616
## Polynomial roots: solve, real_roots, polyroots, nroots
@@ -640,7 +637,7 @@ Unlike `factor` -- which only factors over rational factors --
640637
[Abel-Ruffini theorem](http://en.wikipedia.org/wiki/Abel%E2%80%93Ruffini_theorem))
641638
that for degree 5 polynomials, or higher, it is not always possible to
642639
express the roots in terms of radicals. However, when the roots are
643-
rational `SymPy` can have success:
640+
rational SymPy can have success:
644641

645642

646643
```jldoctest introduction
@@ -658,10 +655,6 @@ julia> real_roots(p)
658655
659656
```
660657

661-
!!! note "Why `string`?"
662-
663-
XXX THIS ISN"T CURRENTLY NEEDED, so we have commented them out. XXX The uses of `string(p)` above and elsewhere throughout the introduction is only for technical reasons related to doctesting and how `Documenter.jl` parses the expected output. This usage is not idiomatic, or suggested; it only allows the cell to be tested programatically for regressions. Similarly, expected errors are wrapped in `try`-`catch` blocks just for testing purposes.
664-
665658

666659
In this example, the degree of `p` is 8, but only the 6 real roots
667660
returned, the double root of $3$ is accounted for. The two complex
@@ -781,8 +774,7 @@ Union(ImageSet(Lambda(_n, 2*_n*pi + 5*pi/4), Integers), ImageSet(Lambda(_n, 2*_n
781774
```
782775

783776
The output of `solveset` is a set, rather than a vector or
784-
dictionary. To get the values requires some work. For *finite sets* we collect the elements
785-
with `collect`, but first we must convert to a `Julia` `Set`:
777+
dictionary.
786778

787779
```jldoctest introduction
788780
julia> v = solveset(x^2 - 4)
@@ -791,32 +783,6 @@ Set{Sym} with 2 elements:
791783
-2
792784
```
793785

794-
```
795-
XXX This is not current
796-
julia> collect(Set(v...))
797-
```
798-
799-
This composition is done in the `elements` function:
800-
801-
```
802-
XXX jldoctest introduction not current
803-
julia> elements(v)
804-
805-
```
806-
807-
!!! note "no elements"
808-
In `SymPyCall` the `elements` function is not used, just use `collect`, as in `collect(v)
809-
810-
```jldoctest introduction
811-
julia> collect(v)
812-
2-element Vector{Sym}:
813-
2
814-
-2
815-
```
816-
817-
818-
The `elements` function does not work for more complicated (non-finite) sets, such as `u`. For these, the `contains` method may be useful to query the underlying elements
819-
820786

821787

822788
Solving within Sympy has limits. For example, there is no symbolic solution here:
@@ -931,7 +897,7 @@ unknowns. When that is not the case, one can specify the variables to
931897
solve for as a vector. In this example, we find a quadratic polynomial
932898
that approximates $\cos(x)$ near $0$:
933899

934-
```julia
900+
```jldoctest introduction
935901
julia> a,b,c,h = symbols("a,b,c,h", real=true)
936902
(a, b, c, h)
937903
@@ -948,20 +914,19 @@ julia> exs = [fn(0*h)-p(x=>0), fn(h)-p(x => h), fn(2h)-p(x => 2h)]
948914
-a*h^2 - b*h - c + cos(h)
949915
-4*a*h^2 - 2*b*h - c + cos(2*h)
950916
951-
julia> d = solve(exs, (a,b,c))
952-
Dict{Any, Any} with 3 entries:
953-
a => -cos(h)/h^2 + cos(2*h)/(2*h^2) + 1/(2*h^2)
954-
c => 1
955-
b => 2*cos(h)/h - cos(2*h)/(2*h) - 3/(2*h)
917+
julia> d = solve(exs, (a,b,c));
918+
919+
julia> d[a], d[b], d[c]
920+
(-cos(h)/h^2 + cos(2*h)/(2*h^2) + 1/(2*h^2), 2*cos(h)/h - cos(2*h)/(2*h) - 3/(2*h), 1)
956921
957922
```
958923

959-
Again, a dictionary is returned. The polynomial itself can be found by
924+
Again, a dictionary is returned, though we display its named elements individually. The polynomial itself can be found by
960925
substituting back in for `a`, `b`, and `c`:
961926

962-
```julia
963-
julia> quad_approx = p.subs(d)#; string(quad_approx)
964-
"x^2*(-cos(h)/h^2 + cos(2*h)/(2*h^2) + 1/(2*h^2)) + x*(2*cos(h)/h - cos(2*h)/(2*h) - 3/(2*h)) + 1"
927+
```jldoctest introduction
928+
julia> quad_approx = p.subs(d)
929+
x^2*(-cos(h)/h^2 + cos(2*h)/(2*h^2) + 1/(2*h^2)) + x*(2*cos(h)/h - cos(2*h)/(2*h) - 3/(2*h)) + 1
965930
966931
```
967932

@@ -971,7 +936,7 @@ Finally for `solve`, we show one way to re-express the polynomial $a_2x^2 + a_1x
971936
as $b_2(x-c)^2 + b_1(x-c) + b_0$ using `solve` (and not, say, an
972937
expansion theorem.)
973938

974-
```julia
939+
```jldoctest introduction
975940
julia> n = 3
976941
3
977942
@@ -988,18 +953,20 @@ julia> p = sum([as[i+1]*x^i for i in 0:(n-1)]);
988953
989954
julia> q = sum([bs[i+1]*(x-c)^i for i in 0:(n-1)]);
990955
991-
julia> solve(p-q, bs)
992-
Dict{Any, Any} with 3 entries:
993-
bs₁ => as₁ + as₂*c + as₃*c^2
994-
bs₂ => as₂ + 2*as₃*c
995-
bs₃ => as₃
956+
julia> d = solve(p-q, bs);
957+
958+
julia> [k => d[k] for k ∈ bs]
959+
3-element Vector{Pair{Sym, Sym}}:
960+
bs₁ => as₁ + as₂*c + as₃*c^2
961+
bs₂ => as₂ + 2*as₃*c
962+
bs₃ => as₃
996963
997964
```
998965

999966

1000967
### Solving using logical operators
1001968

1002-
The `solve` function does not need to just solve `ex = 0`. There are other means to specify an equation. Ideally, it would be nice to say `ex1 == ex2`, but the interpretation of `==` is not for this. Rather, `SymPy` introduces `Eq` for equality. So this expression
969+
The `solve` function does not need to just solve `ex = 0`. There are other means to specify an equation. Ideally, it would be nice to say `ex1 == ex2`, but the interpretation of `==` is not for this. Rather, `SymPyCall` introduces `Eq` for equality. So this expression
1003970

1004971
```jldoctest introduction
1005972
julia> solve(Eq(x, 1))
@@ -1026,7 +993,7 @@ julia> solve(x ⩵ 1)
1026993

1027994
Here is an alternative way of asking a previous question on a pair of linear equations:
1028995

1029-
```julia
996+
```jldoctest introduction
1030997
julia> x, y = symbols("x,y", real=true)
1031998
(x, y)
1032999
@@ -1035,10 +1002,10 @@ julia> exs = [2x+3y ⩵ 6, 3x-4y ⩵ 12] ## Using \Equal[tab]
10351002
2⋅x + 3⋅y = 6
10361003
3⋅x - 4⋅y = 12
10371004
1038-
julia> d = solve(exs)
1039-
Dict{Any, Any} with 2 entries:
1040-
x => 60/17
1041-
y => -6/17
1005+
julia> d = solve(exs);
1006+
1007+
julia> d[x], d[y]
1008+
(Fraction(60, 17), Fraction(-6, 17))
10421009
10431010
```
10441011

0 commit comments

Comments
 (0)