library(caracas)
<- symbol('x')
x as.character(x)
#> [1] "x"
x#> [caracas]: x
as_expr(x)
#> expression(x)
2*x
#> [caracas]: 2⋅x
<- symbol('y')
y sqrt(3*x^y)
#> [caracas]: ____
#> ╱ y
#> √3⋅╲╱ x
<- cos(x)^2 + sin(x)^2
z
z#> [caracas]: 2 2
#> sin (x) + cos (x)
simplify(z)
#> [caracas]: 1
tex(z)
#> [1] "\\sin^{2}{\\left(x \\right)} + \\cos^{2}{\\left(x \\right)}"
<- cos(x)*cos(y) - sin(x)*sin(y)
z
z#> [caracas]: -sin(x)⋅sin(y) + cos(x)⋅cos(y)
simplify(z)
#> [caracas]: cos(x + y)
<- cos(x + y)
z
z#> [caracas]: cos(x + y)
expand(z)
#> [caracas]: cos(x + y)
expand_trig(z)
#> [caracas]: -sin(x)⋅sin(y) + cos(x)⋅cos(y)
<- symbol('x')
x <- symbol('y')
y <- log(x*y)
z
z#> [caracas]: log(x⋅y)
expand_log(z)
#> [caracas]: log(x) + log(y)
<- symbol("x")
x sum_(1/x, "x", 1, 10)
#> [caracas]: 7381
#> ────
#> 2520
sum_(1/x, x, 1, 10)
#> [caracas]: 7381
#> ────
#> 2520
<- sum_(1/x, "x", 1, 10)
s as_expr(s)
#> [1] 2.928968
sum(1/(1:10))
#> [1] 2.928968
<- symbol("n")
n simplify(sum_(x, x, 1, n))
#> [caracas]: n⋅(n + 1)
#> ─────────
#> 2
<- symbol("x")
x <- prod_(1/x, "x", 1, 10)
p
p#> [caracas]: 1/3628800
as_expr(p)
#> [1] 2.755732e-07
prod(1/(1:10))
#> [1] 2.755732e-07
<- symbol("n")
n prod_(x, x, 1, n)
#> [caracas]: n!
<- symbol("x")
x
int(1/x, x, 1, 10)
#> [caracas]: log(10)
<- int(1/x, x, 1, 10, doit = FALSE)
i1
i1#> [caracas]: 10
#> ⌠
#> ⎮ 1
#> ⎮ ─ dx
#> ⎮ x
#> ⌡
#> 1
tex(i1)
#> [1] "\\int\\limits_{1}^{10} \\frac{1}{x}\\, dx"
doit(i1)
#> [caracas]: log(10)
int(1/x, x)
#> [caracas]: log(x)
<- int(1/x, x, doit = FALSE)
i1
i1#> [caracas]: ⌠
#> ⎮ 1
#> ⎮ ─ dx
#> ⎮ x
#> ⌡
tex(i1)
#> [1] "\\int \\frac{1}{x}\\, dx"
doit(i1)
#> [caracas]: log(x)
<- symbol("x")
x lim(sin(x)/x, "x", 0)
#> [caracas]: 1
lim(1/x, "x", 0, dir = '+')
#> [caracas]: ∞
lim(1/x, "x", 0, dir = '-')
#> [caracas]: -∞
We can also postpone evaluation:
<- symbol("x")
x lim(sin(x)/x, "x", 0)
#> [caracas]: 1
lim(sin(x)/x, x, 0)
#> [caracas]: 1
<- lim(sin(x)/x, "x", 0, doit = FALSE)
res
res#> [caracas]: ⎛sin(x)⎞
#> lim ⎜──────⎟
#> x─→0⁺⎝ x ⎠
as.character(res)
#> [1] "Limit(sin(x)/x, x, 0)"
tex(res)
#> [1] "\\lim_{x \\to 0^+}\\left(\\frac{\\sin{\\left(x \\right)}}{x}\\right)"
doit(res)
#> [caracas]: 1
as_expr(res)
#> [1] 1
Note that the function is called d()
and not deriv()
.
<- symbol("x")
x <- symbol("y")
y <- 3*x^2 + x*y^2
f
f#> [caracas]: 2 2
#> 3⋅x + x⋅y
as_expr(f)
#> expression(3 * x^2 + x * y^2)
der(f, "x")
#> [caracas]: 2
#> 6⋅x + y
der(f, x)
#> [caracas]: 2
#> 6⋅x + y
der(f, c("x", "y"))
#> [caracas]: ⎡ 2 ⎤
#> ⎣6⋅x + y 2⋅x⋅y⎦
der(f, list(x, y))
#> [caracas]: ⎡ 2 ⎤
#> ⎣6⋅x + y 2⋅x⋅y⎦
<- der(f, list(x, y))
f1
f1#> [caracas]: ⎡ 2 ⎤
#> ⎣6⋅x + y 2⋅x⋅y⎦
as.character(f1)
#> [1] "[6*x + y^2, 2*x*y]"
as_expr(f1)
#> expression(cbind(6 * x + y^2, 2 * x * y))
eval(as_expr(f1), list(x = 1, y = 2))
#> [,1] [,2]
#> [1,] 10 4
der(f1, list(x, y))
#> [caracas]: ⎡ 6 2⋅y⎤
#> ⎢ ⎥
#> ⎣2⋅y 2⋅x⎦
<- der2(f, list(x, y))
f2
f2#> [caracas]: ⎡ 6 2⋅y⎤
#> ⎢ ⎥
#> ⎣2⋅y 2⋅x⎦
as_expr(f2)
#> expression(rbind(cbind(6, 2 * y), cbind(2 * y, 2 * x)))
eval(as_expr(f2), list(x = 1, y = 2))
#> [,1] [,2]
#> [1,] 6 4
#> [2,] 4 2
<- symbol("x")
x <- symbol("y")
y <- eval_to_symbol("[3*x**2 + x*y**2, 2*x, 5*y]")
f
f#> [caracas]: ⎡ 2 2 ⎤
#> ⎣3⋅x + x⋅y , 2⋅x, 5⋅y⎦
der(f, list(x, y))
#> [caracas]: ⎡ 2 ⎤
#> ⎢6⋅x + y 2 0⎥
#> ⎢ ⎥
#> ⎣ 2⋅x⋅y 0 5⎦
def_sym(x)
<- cos(x)
f <- taylor(f, x0 = 0, n = 4+1)
ft_with_O
ft_with_O#> [caracas]: 2 4
#> x x ⎛ 5.0⎞
#> 1 - ── + ── + O⎝x ⎠
#> 2 24
%>% drop_remainder() %>% as_expr()
ft_with_O #> expression(x^4/24 - x^2/2 + 1)
<- matrix(c("x", 0, 0, "2*x"), 2, 2)
A
A#> [,1] [,2]
#> [1,] "x" "0"
#> [2,] "0" "2*x"
<- as_sym(A)
B
B#> [caracas]: ⎡x 0 ⎤
#> ⎢ ⎥
#> ⎣0 2⋅x⎦
2*B
#> [caracas]: ⎡2⋅x 0 ⎤
#> ⎢ ⎥
#> ⎣ 0 4⋅x⎦
*B # Component-wise / Hadamard product
B#> [caracas]: ⎡ 2 ⎤
#> ⎢x 0 ⎥
#> ⎢ ⎥
#> ⎢ 2⎥
#> ⎣0 4⋅x ⎦
dim(B)
#> [1] 2 2
sqrt(B)
#> [caracas]: ⎡√x 0 ⎤
#> ⎢ ⎥
#> ⎣0 √2⋅√x⎦
log(B)
#> [caracas]: ⎡log(x) zoo ⎤
#> ⎢ ⎥
#> ⎣ zoo log(2⋅x)⎦
sum(B)
#> [caracas]: 3⋅x
%*% t(B)
B #> [caracas]: ⎡ 2 ⎤
#> ⎢x 0 ⎥
#> ⎢ ⎥
#> ⎢ 2⎥
#> ⎣0 4⋅x ⎦
diag(B)
#> [caracas]: [x 2⋅x]
cbind(B, B)
#> [caracas]: ⎡x 0 x 0 ⎤
#> ⎢ ⎥
#> ⎣0 2⋅x 0 2⋅x⎦
rbind(B, B)
#> [caracas]: ⎡x 0 ⎤
#> ⎢ ⎥
#> ⎢0 2⋅x⎥
#> ⎢ ⎥
#> ⎢x 0 ⎥
#> ⎢ ⎥
#> ⎣0 2⋅x⎦
det(B)
#> [caracas]: 2
#> 2⋅x
QRdecomposition(B)
#> $Q
#> [caracas]: ⎡ x ⎤
#> ⎢─── 0 ⎥
#> ⎢│x│ ⎥
#> ⎢ ⎥
#> ⎢ x ⎥
#> ⎢ 0 ───⎥
#> ⎣ │x│⎦
#>
#> $R
#> [caracas]: ⎡│x│ 0 ⎤
#> ⎢ ⎥
#> ⎣ 0 2⋅│x│⎦
<- matrix(c("a", 0, 0, 0, "a", "a", "a", 0, 0), 3, 3)
A <- as_sym(A)
B eigenval(B)
#> [[1]]
#> [[1]]$eigval
#> [caracas]: a
#>
#> [[1]]$eigmult
#> [1] 2
#>
#>
#> [[2]]
#> [[2]]$eigval
#> [caracas]: 0
#>
#> [[2]]$eigmult
#> [1] 1
eigenvec(B)
#> [[1]]
#> [[1]]$eigval
#> [caracas]: 0
#>
#> [[1]]$eigmult
#> [1] 1
#>
#> [[1]]$eigvec
#> [caracas]: [-1 0 1]ᵀ
#>
#>
#> [[2]]
#> [[2]]$eigval
#> [caracas]: a
#>
#> [[2]]$eigmult
#> [1] 2
#>
#> [[2]]$eigvec
#> [caracas]: [1 0 0]ᵀ
eigen(eval(as_expr(B), list(a = 2)))
#> eigen() decomposition
#> $values
#> [1] 2 2 0
#>
#> $vectors
#> [,1] [,2] [,3]
#> [1,] 1 -1.000000e+00 -0.7071068
#> [2,] 0 2.220446e-16 0.0000000
#> [3,] 0 2.220446e-16 0.7071068
B#> [caracas]: ⎡a 0 a⎤
#> ⎢ ⎥
#> ⎢0 a 0⎥
#> ⎢ ⎥
#> ⎣0 a 0⎦
diag(B)
#> [caracas]: [a a 0]
diag(B) <- "b"
B#> [caracas]: ⎡b 0 a⎤
#> ⎢ ⎥
#> ⎢0 b 0⎥
#> ⎢ ⎥
#> ⎣0 a b⎦
diag(B)[-2] <- "a"
B#> [caracas]: ⎡a 0 a⎤
#> ⎢ ⎥
#> ⎢0 b 0⎥
#> ⎢ ⎥
#> ⎣0 a a⎦
inv()
/ solve_lin()
solve_sys()
Below find an example with maximising the multinomial likelihood.
<- as_sym(paste0("p", 1:3))
p <- as_sym(paste0("y", 1:3))
y <- as_sym("a")
a <- sum(y*log(p))
l
l#> [caracas]: y₁⋅log(p₁) + y₂⋅log(p₂) + y₃⋅log(p₃)
<- -l + a*(sum(p) - 1)
L
L#> [caracas]: a⋅(p₁ + p₂ + p₃ - 1) - y₁⋅log(p₁) - y₂⋅log(p₂) - y₃⋅log(p₃)
tex(L)
#> [1] "a \\left(p_{1} + p_{2} + p_{3} - 1\\right) - y_{1} \\log{\\left(p_{1} \\right)} - y_{2} \\log{\\left(p_{2} \\right)} - y_{3} \\log{\\left(p_{3} \\right)}"
<- der(L, list(p, a))
g
g#> [caracas]: ⎡ y₁ y₂ y₃ ⎤
#> ⎢a - ── a - ── a - ── p₁ + p₂ + p₃ - 1⎥
#> ⎣ p₁ p₂ p₃ ⎦
<- solve_sys(g, list(p, a))
sol
sol#> Solution 1:
#> p1 = y₁
#> ────────────
#> y₁ + y₂ + y₃
#> p2 = y₂
#> ────────────
#> y₁ + y₂ + y₃
#> p3 = y₃
#> ────────────
#> y₁ + y₂ + y₃
#> a = y₁ + y₂ + y₃
$p1
sol[[1L]]#> [caracas]: y₁
#> ────────────
#> y₁ + y₂ + y₃
tex(sol[[1L]]$p1)
#> [1] "\\frac{y_{1}}{y_{1} + y_{2} + y_{3}}"
<- symbol('x')
x <- 2*x^2 - x
eq
eq#> [caracas]: 2
#> 2⋅x - x
subs(eq, x, "y")
#> [caracas]: 2
#> 2⋅y - y
<- as_sym(paste0("p", 1:3))
p <- as_sym(paste0("y", 1:3))
y <- as_sym("a")
a <- sum(y*log(p))
l <- -l + a*(sum(p) - 1)
L <- der(L, c(a, p))
g <- solve_sys(g, list(a, p))
sols <- sols[[1L]]
sol
sol#> $a
#> [caracas]: -y₁
#> ───────────
#> p₂ + p₃ - 1
#>
#> $p1
#> [caracas]: -p₂ - p₃ + 1
<- der2(L, list(p, a))
H
H#> [caracas]: ⎡ y₁ ⎤
#> ⎢─── 0 0 1⎥
#> ⎢ 2 ⎥
#> ⎢p₁ ⎥
#> ⎢ ⎥
#> ⎢ y₂ ⎥
#> ⎢ 0 ─── 0 1⎥
#> ⎢ 2 ⎥
#> ⎢ p₂ ⎥
#> ⎢ ⎥
#> ⎢ y₃ ⎥
#> ⎢ 0 0 ─── 1⎥
#> ⎢ 2 ⎥
#> ⎢ p₃ ⎥
#> ⎢ ⎥
#> ⎣ 1 1 1 0⎦
<- subs_lst(H, sol)
H_sol
H_sol#> [caracas]: ⎡ y₁ ⎤
#> ⎢─────────────── 0 0 1⎥
#> ⎢ 2 ⎥
#> ⎢(-p₂ - p₃ + 1) ⎥
#> ⎢ ⎥
#> ⎢ y₂ ⎥
#> ⎢ 0 ─── 0 1⎥
#> ⎢ 2 ⎥
#> ⎢ p₂ ⎥
#> ⎢ ⎥
#> ⎢ y₃ ⎥
#> ⎢ 0 0 ─── 1⎥
#> ⎢ 2 ⎥
#> ⎢ p₃ ⎥
#> ⎢ ⎥
#> ⎣ 1 1 1 0⎦
Note that all vectors in caracas
are column vectors.
<- matrix(c("a", 0, 0, 0, "a", "a", "a", 0, 0), 3, 3)
A <- as_sym(A)
B 2]
B[, #> [caracas]: [0 a a]ᵀ
-2]
B[, #> [caracas]: ⎡a a⎤
#> ⎢ ⎥
#> ⎢0 0⎥
#> ⎢ ⎥
#> ⎣0 0⎦
1, ]
B[#> [caracas]: [a 0 a]ᵀ
1, , drop = FALSE] # Note this is a 1x3 matrix
B[#> [caracas]: [a 0 a]
2] <- "x"
B[,
B#> [caracas]: ⎡a x a⎤
#> ⎢ ⎥
#> ⎢0 x 0⎥
#> ⎢ ⎥
#> ⎣0 x 0⎦
SymPy
directly<- get_sympy() sympy
$diff("2*a*x", "x")
sympy#> 2*a
$solve("x**2 - 1", "x")
sympy#> [[1]]
#> -1
#>
#> [[2]]
#> 1
Below we give a brief example of assumptions. First consider the Cholesky decomposition of a matrix:
<- matrix(c("x+1", 1, 1, 1), 2, 2) %>% as_sym()
A
A#> [caracas]: ⎡x + 1 1⎤
#> ⎢ ⎥
#> ⎣ 1 1⎦
do_la(A, "cholesky")
#> Error in py_call_impl(callable, dots$args, dots$keywords): ValueError: Matrix must be Hermitian.
#>
#> Detailed traceback:
#> File "/home/mikl/.local/lib/python3.7/site-packages/sympy/matrices/matrices.py", line 2855, in cholesky
#> raise ValueError("Matrix must be Hermitian.")
This fails as A
is not positive (semi-)definite.
To ensure this, we need to impose restrictions on x
. This is done by defining a symbol with an assumption about positivity:
<- symbol("y", positive = TRUE) y
We continue and define B
, where it is important that declare_symbols = FALSE
or else a new y
will automatically be defined by caracas
overwriting the above definition:
<- as_sym("[[y + 1, 1], [1, 1]]", declare_symbols = FALSE)
B
B#> [caracas]: ⎡y + 1 1⎤
#> ⎢ ⎥
#> ⎣ 1 1⎦
do_la(B, "cholesky")
#> [caracas]: ⎡ _______ ⎤
#> ⎢╲╱ y + 1 0 ⎥
#> ⎢ ⎥
#> ⎢ ___________⎥
#> ⎢ 1 ╱ 1 ⎥
#> ⎢───────── ╱ 1 - ───── ⎥
#> ⎢ _______ ╲╱ y + 1 ⎥
#> ⎣╲╱ y + 1 ⎦
It is possible to ask for properties (see https://docs.sympy.org/latest/modules/assumptions/ask.html):
ask(y, "positive")
#> [1] TRUE
ask(B, "hermitian")
#> [1] TRUE
ask(A, "hermitian")
#> [1] NA
# Multinomial likelihood
<- as_sym(paste0("p", 1:3))
p <- as_sym(paste0("y", 1:3))
y <- as_sym("a")
a <- sum(y*log(p))
l <- -l + a*(sum(p) - 1)
L
L#> [caracas]: a⋅(p₁ + p₂ + p₃ - 1) - y₁⋅log(p₁) - y₂⋅log(p₂) - y₃⋅log(p₃)
print(L, ascii = TRUE)
#> [caracas]: a*(p1 + p2 + p3 - 1) - y1*log(p1) - y2*log(p2) - y3*log(p3)
<- der(L, list(p, a))
g <- solve_sys(g, list(p, a))
sol
sol#> Solution 1:
#> p1 = y₁
#> ────────────
#> y₁ + y₂ + y₃
#> p2 = y₂
#> ────────────
#> y₁ + y₂ + y₃
#> p3 = y₃
#> ────────────
#> y₁ + y₂ + y₃
#> a = y₁ + y₂ + y₃
print(sol, simplify = FALSE)
#> [[1]]
#> [[1]]$p1
#> [caracas]: y₁
#> ────────────
#> y₁ + y₂ + y₃
#>
#> [[1]]$p2
#> [caracas]: y₂
#> ────────────
#> y₁ + y₂ + y₃
#>
#> [[1]]$p3
#> [caracas]: y₃
#> ────────────
#> y₁ + y₂ + y₃
#>
#> [[1]]$a
#> [caracas]: y₁ + y₂ + y₃
as.character(g)
#> [1] "[a - y1/p1, a - y2/p2, a - y3/p3, p1 + p2 + p3 - 1]"
as_character_matrix(g)
#> [,1] [,2] [,3] [,4]
#> [1,] "a - y1/p1" " a - y2/p2" " a - y3/p3" " p1 + p2 + p3 - 1"
The following options are available:
caracas.print.prettyascii
caracas.print.ascii
caracas.print.rowvec
caracas.print.sol.simplify
sol#> Solution 1:
#> p1 = y₁
#> ────────────
#> y₁ + y₂ + y₃
#> p2 = y₂
#> ────────────
#> y₁ + y₂ + y₃
#> p3 = y₃
#> ────────────
#> y₁ + y₂ + y₃
#> a = y₁ + y₂ + y₃
L#> [caracas]: a⋅(p₁ + p₂ + p₃ - 1) - y₁⋅log(p₁) - y₂⋅log(p₂) - y₃⋅log(p₃)
options(caracas.print.prettyascii = TRUE)
sol#> Solution 1:
#> p1 = y1
#> ------------
#> y1 + y2 + y3
#> p2 = y2
#> ------------
#> y1 + y2 + y3
#> p3 = y3
#> ------------
#> y1 + y2 + y3
#> a = y1 + y2 + y3
L#> [caracas]: a*(p1 + p2 + p3 - 1) - y1*log(p1) - y2*log(p2) - y3*log(p3)
options(caracas.print.prettyascii = NULL) # reset to default (FALSE)
sol#> Solution 1:
#> p1 = y₁
#> ────────────
#> y₁ + y₂ + y₃
#> p2 = y₂
#> ────────────
#> y₁ + y₂ + y₃
#> p3 = y₃
#> ────────────
#> y₁ + y₂ + y₃
#> a = y₁ + y₂ + y₃
L#> [caracas]: a⋅(p₁ + p₂ + p₃ - 1) - y₁⋅log(p₁) - y₂⋅log(p₂) - y₃⋅log(p₃)
options(caracas.print.ascii = TRUE)
sol#> Solution 1:
#> p1 = y1/(y1 + y2 + y3)
#> p2 = y2/(y1 + y2 + y3)
#> p3 = y3/(y1 + y2 + y3)
#> a = y1 + y2 + y3
L#> [caracas]: a*(p1 + p2 + p3 - 1) - y1*log(p1) - y2*log(p2) - y3*log(p3)
options(caracas.print.ascii = NULL) # reset to default (FALSE)
p#> [caracas]: [p₁ p₂ p₃]ᵀ
options(caracas.print.rowvec = FALSE)
p#> [caracas]: ⎡p₁⎤
#> ⎢ ⎥
#> ⎢p₂⎥
#> ⎢ ⎥
#> ⎣p₃⎦
options(caracas.print.rowvec = NULL) # reset to default (TRUE)
sol#> Solution 1:
#> p1 = y₁
#> ────────────
#> y₁ + y₂ + y₃
#> p2 = y₂
#> ────────────
#> y₁ + y₂ + y₃
#> p3 = y₃
#> ────────────
#> y₁ + y₂ + y₃
#> a = y₁ + y₂ + y₃
options(caracas.print.sol.simplify = FALSE)
sol#> [[1]]
#> [[1]]$p1
#> [caracas]: y₁
#> ────────────
#> y₁ + y₂ + y₃
#>
#> [[1]]$p2
#> [caracas]: y₂
#> ────────────
#> y₁ + y₂ + y₃
#>
#> [[1]]$p3
#> [caracas]: y₃
#> ────────────
#> y₁ + y₂ + y₃
#>
#> [[1]]$a
#> [caracas]: y₁ + y₂ + y₃
options(caracas.print.sol.simplify = NULL) # reset to default (TRUE)