Skip to content

Commit ffc46bf

Browse files
authored
close issue #354; close issue #355 (#356)
* close issue #354; close issue #355
1 parent 77b8ea0 commit ffc46bf

File tree

4 files changed

+81
-21
lines changed

4 files changed

+81
-21
lines changed

β€ŽProject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "SymPy"
22
uuid = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6"
3-
version = "1.0.24"
3+
version = "1.0.25"
44

55

66
[deps]

β€Žsrc/assumptions.jl

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ export ask
3535
## We make a module Q to hold the assumptions
3636
## this follows this page http://docs.sympy.org/0.7.5/_modules/sympy/assumptions/ask.html
3737
"""
38+
𝑄
39+
SymPy.Q
3840
39-
Documentation for the `Q` module.
41+
Documentation for the `SymPy.Q` module, exported as `𝑄`.
4042
4143
SymPy allows for
42-
[assumptions](http://docs.sympy.org/latest/modules/sympy/assumptions/)
44+
[assumptions](https://docs.sympy.org/latest/modules/assumptions/index.html)
4345
on variables. These may be placed on free sympols at construction.
4446
4547
For example, the following creates a real value variable `x` and a postive, real variable `y`:
@@ -53,11 +55,11 @@ The `Q` module exposes a means to *q*uery the assumptions on a
5355
variable. For example,
5456
5557
```
56-
ask(Q.positive(y)) # true
57-
ask(Q.negative(y)) # false
58-
ask(Q.positive(x)) # `nothing`
59-
ask(Q.positive(x^2)) # `nothing` -- might be 0
60-
ask(Q.positive(1 + x^2) # true -- must be postive now.
58+
ask(𝑄.positive(y)) # true
59+
ask(𝑄.negative(y)) # false
60+
ask(SymPy.Q.positive(x)) # `nothing`
61+
ask(SymPy.Q.positive(x^2)) # `nothing` -- might be 0
62+
ask(SymPy.Q.positive(1 + x^2) # true -- must be postive now.
6163
```
6264
6365
The ask function uses tri-state logic, returning one of 3 values:
@@ -67,14 +69,15 @@ The construction of predicates is done through `Q` methods. These can
6769
be combined logically. For example, this will be `true`:
6870
6971
```
70-
ask(Q.positive(y) & Q.negative(-x^2 - 1))
72+
ask(𝑄.positive(y) & 𝑄.negative(-x^2 - 1))
7173
```
7274
7375
The above use `&` as an infix operation for the binary operator
7476
`And`. Values can also be combined with `Or`, `Not`, `Xor`, `Nand`,
7577
`Nor`, `Implies`, `Equivalent`, and `satisfiable`.
7678
77-
Note: As `SymPy.jl` converts symbolic matrices into Julia's `Array`
79+
!!! note:
80+
As `SymPy.jl` converts symbolic matrices into Julia's `Array`
7881
type and not as matrices within Python, the predicate functions from SymPy for
7982
matrices are not used, though a replacement is given.
8083
"""
@@ -315,5 +318,22 @@ end
315318

316319
end
317320

321+
## Issue #354; request to *not* export Q
318322
## export
319-
export Q
323+
#export Q
324+
325+
const 𝑄 = Q
326+
327+
"""
328+
𝑄
329+
330+
Exported symbol for [`SymPy.Q`](@ref), a Julia module implementing `sympy.Q`. "Questions" can be asked through the patterns
331+
`𝑄.query(value)` (𝑄 is entered as [slash]itQ[tab]) or `SymPy.Q.query(value)` *but not* as `sympy.Q.query(value)`
332+
333+
!!! note
334+
At one time, the symbol `Q` was exported for this. To avoid namespace clutter, the unicode alternative is now used. Legacy code would need a definition like `const Q = SymPy.Q` to work.
335+
336+
"""
337+
𝑄
338+
export 𝑄
339+

β€Žsrc/matrix.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,26 @@ function LinearAlgebra.eigvecs(a::Matrix{Sym})
8181
hcat((hcat(di[3]...) for di in ds)...)
8282
end
8383

84+
# solve Ax=b for x, avoiding generic `lu`, which can be very slow for bigger n values
85+
# fix suggested by @olof3 in issue 355
86+
function LinearAlgebra.:\(A::AbstractArray{Sym,2}, b::AbstractArray{S,1}) where {S}
87+
88+
m,n = size(A)
89+
x = Sym["x$i" for i in 1:n]
90+
out = solve(A*x-b, x)
91+
isempty(out) && throw(SingularException(0)) # Could also return out here?
92+
ret = Vector{Sym}(undef, n)
93+
for (i,xα΅’) in enumerate(x)
94+
ret[i] = get(out, xα΅’, xα΅’)
95+
end
96+
97+
return ret
8498

99+
end
100+
101+
function LinearAlgebra.:\(A::AbstractArray{T,2}, B::AbstractArray{S,2}) where {T <: Sym, S}
102+
hcat([A \ bβ±Ό for bβ±Ό in eachcol(B)]...)
103+
end
85104

86105

87106
##################################################

β€Žtest/tests.jl

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,28 @@ import PyCall
196196
@test_throws MethodError nsolve([z1^2-1, z1+z2z1-2], [z1,z2z1], [1,1]) # non symbolic first argument
197197
@test all(N.(sympy.nsolve([z1^2-1, z1+z2z1-2], [z1,z2z1], (1,1))) .β‰ˆ [1.0, 1.0])
198198

199+
## issue 355: direct definition of LinearAlgebra.:\
200+
@test_throws SingularException Sym[1 1; 1 1] \ [1, 2]
201+
@vars a b c d e f
202+
A, b= [a b; c d], [e, f]
203+
x = A \ b
204+
@test simplify.(A*x-b) == [0,0]
205+
out = Sym[1 1; 1 1] \ [1,1]
206+
u = free_symbols(out)[1]
207+
@test out == [1-u,u]
208+
209+
210+
# Just a made-up example to test if manageable
211+
@vars a1 a2
212+
n = 7
213+
A = diagm(0 => ones(Int, n), 1 => fill(a1, n-1), 2 => fill(1, n-2), -1 => fill(a2, n-1))
214+
b = Vector{Sym}(1:n)
215+
x = A \ b
216+
@test length(free_symbols(x)) == 2
217+
218+
199219
## limits
220+
@vars x
200221
@test limit(x -> sin(x)/x, 0) == 1
201222
@test limit(sin(x)/x, x, 0) |> float == 1
202223
@test limit(sin(x)/x, x => 0) == 1
@@ -429,16 +450,16 @@ import PyCall
429450
end
430451

431452
## Assumptions
432-
@test ask(Q.even(Sym(2))) == true
433-
@test ask(Q.even(Sym(3))) == false
434-
@test ask(Q.nonzero(Sym(3))) == true
453+
@test ask(𝑄.even(Sym(2))) == true
454+
@test ask(𝑄.even(Sym(3))) == false
455+
@test ask(𝑄.nonzero(Sym(3))) == true
435456
@vars x_real real=true
436457
@vars x_real_positive real=true positive=true
437-
@test ask(Q.positive(x_real)) == nothing
438-
@test ask(Q.positive(x_real_positive)) == true
439-
@test ask(Q.nonnegative(x_real^2)) == true
440-
@test ask(Q.upper_triangular([x_real 1; 0 x_real])) == true
441-
@test ask(Q.positive_definite([x_real 1; 1 x_real])) == nothing
458+
@test ask(𝑄.positive(x_real)) == nothing
459+
@test ask(𝑄.positive(x_real_positive)) == true
460+
@test ask(𝑄.nonnegative(x_real^2)) == true
461+
@test ask(𝑄.upper_triangular([x_real 1; 0 x_real])) == true
462+
@test ask(𝑄.positive_definite([x_real 1; 1 x_real])) == nothing
442463

443464

444465
## sets
@@ -549,8 +570,8 @@ end
549570
# issue 231 Q.complex
550571
@vars x_maybecomplex
551572
@vars x_imag imaginary=true
552-
@test ask(Q.complex(x_maybecomplex)) == nothing
553-
@test ask(Q.complex(x_imag)) == true
573+
@test ask(𝑄.complex(x_maybecomplex)) == nothing
574+
@test ask(𝑄.complex(x_imag)) == true
554575

555576
# issue 242 lambdify and conjugate
556577
@vars x

0 commit comments

Comments
Β (0)