03 - Objects in ‘caracas’

library(caracas)

Variables, names, symbols etc.

We can think of a variable as a piece of memory in a computer. A variable typically also has a name (also called a symbol). That name/symbol is used to refer to the variable; that is, the name / symbol is a handle on the variable. It is like the difference between you and your name.

There are different ways of creating a variable in caracas. One is as

symbol("a")
#> c: a

which creates a SymPy variable a but provides no handle on it (no R-symbol). We can get an R-handle on a SymPy variable with

b <- symbol("a")
a <- symbol("b")

where we do something very confusing: Assign the R-name a to the SymPy variable b and vice versa. We can compute on variable b in SymPy by manipulating the symbol a in R, e.g.

a + 1
#> c: b + 1
a <- a + 1
a / b
#> c: b + 1
#>    ─────
#>      a

A text representation of a symbol can be found as:

a %>% print.default()
#> $pyobj
#> b + 1
#> 
#> attr(,"class")
#> [1] "caracas_symbol"
a %>% as.character()
#> [1] "b + 1"

Usually, the best practice is to assign R symbols to SymPy variables of the same name. To avoid confusion, symbol names and Python variable names will always coincide.

Creating symbols

In addition to symbol() illustrated above, multiple R-symbols / Python-variables can be defined using def_sym and def_sym_vec

def_sym(u, v)
def_sym("w", "x")
def_sym_vec(c("y", "z"))

With this, R-symbols u, v, w, x exist and each are connected to Python variables with the same name

u; v; w; x; y; z
#> c: u
#> c: v
#> c: w
#> c: x
#> c: y
#> c: z

A third way for creating a symbol with as_sym. First notice:

as_sym("l1")
#> c: l₁
# same as symbol("l1")
l2 <- as_sym("l2"); l2
#> c: l₂
# same as def_sym("l2")

More interestingly

m_ <- paste0("m", 1:4)
m <- as_sym(m_)
m
#> c: [m₁  m₂  m₃  m₄]ᵀ

B_ <- matrix(c("x", 2, 0, "2*x"), 2, 2)
B <- as_sym(B_)

Classes

Above, r is a \(4 \times 1\) matrix, while e.g. u is an atom:

m %>% symbol_class()
#> [1] "matrix"
u %>% symbol_class()
#> [1] "atomic"

We can coerce between different “classes” (we quote the word because it is not a class system as e.g. those known from R) A text representation of the variables are:

m %>% as.character()
#> [1] "Matrix([[m1], [m2], [m3], [m4]])"
u %>% as.character()
#> [1] "u"

While not often needed that are also lists and vectors in Python. In caracas they are created by coercion:

u %>% to_list()
#> c: [[u]]
u %>% to_vector()
#> c: [u]
m %>% to_list()
#> c: [[m₁], [m₂], [m₃], [m₄]]
m %>% to_vector()
#> c: [m₁, m₂, m₃, m₄]

The corresponding text representations are:

u %>% to_list() %>% as.character()
#> [1] "[[u]]"
u %>% to_vector() %>% as.character()
#> [1] "[u]"
m %>% to_list() %>% as.character()
#> [1] "[[m1], [m2], [m3], [m4]]"
m %>% to_vector() %>% as.character()
#> [1] "[m1, m2, m3, m4]"

Likewise:

m %>% to_matrix()
#> c: [m₁  m₂  m₃  m₄]ᵀ
u %>% to_matrix()
#> c: [u]

Indexing

Let

v <- m %>% to_vector()
l <- m %>% to_list()
V <- matrix_sym(2, 2)

Quick start

def_sym('x', 'y')
eq <- 2*x^2 - x - y
eq
#> c:    2        
#>    2⋅x  - x - y
as.character(eq)
#> [1] "2*x^2 - x - y"
as_expr(eq)
#> expression(2 * x^2 - x - y)
tex(eq)
#> [1] "2 x^{2} - x - y"

\[2 x^{2} - x - y\]

sol <- solve_sys(eq, x)
sol
#> x =       _________
#> 1   ╲╱ 8⋅y + 1 
#> ─ - ───────────
#> 4        4
#> x =   _________    
#> ╲╱ 8⋅y + 1    1
#> ─────────── + ─
#>      4        4
# Access solutions
sol[[1]]$x
#> c:       _________
#>    1   ╲╱ 8⋅y + 1 
#>    ─ - ───────────
#>    4        4
sol[[2]]$x
#> c:   _________    
#>    ╲╱ 8⋅y + 1    1
#>    ─────────── + ─
#>         4        4

dx <- der(eq, x)
dx
#> c: 4⋅x - 1
dx %>% symbol_class()
#> [1] "atomic"

dxy <- der(eq, c(x, y))
dxy
#> c: [4⋅x - 1  -1]
dxy %>% symbol_class()
#> [1] "vector"

subs(eq, x, y)
#> c:    2      
#>    2⋅y  - 2⋅y

Linear algebra

B_ <- matrix(c("x", 2, 0, "2*x"), 2, 2)
B <- as_sym(B_)
B
#> c: ⎡x   0 ⎤
#>    ⎢      ⎥
#>    ⎣2  2⋅x⎦
Binv <- inv(B) # or solve_lin(B)
Binv
#> c: ⎡ 1      ⎤
#>    ⎢ ─    0 ⎥
#>    ⎢ x      ⎥
#>    ⎢        ⎥
#>    ⎢-1    1 ⎥
#>    ⎢───  ───⎥
#>    ⎢  2  2⋅x⎥
#>    ⎣ x      ⎦
tex(Binv)
#> [1] "\\left[\\begin{matrix}\\frac{1}{x} & 0\\\\- \\frac{1}{x^{2}} & \\frac{1}{2 x}\\end{matrix}\\right]"
det(B)
#> c:    2
#>    2⋅x
Binv * det(B)
#> c: ⎡2⋅x  0⎤
#>    ⎢      ⎥
#>    ⎣-2   x⎦

\[\left[\begin{matrix}\frac{1}{x} & 0\\- \frac{1}{x^{2}} & \frac{1}{2 x}\end{matrix}\right]\]

eigenval(Binv)
#> [[1]]
#> [[1]]$eigval
#> c: 1
#>    ─
#>    x
#> 
#> [[1]]$eigmult
#> [1] 1
#> 
#> 
#> [[2]]
#> [[2]]$eigval
#> c:  1 
#>    ───
#>    2⋅x
#> 
#> [[2]]$eigmult
#> [1] 1
eigenvec(Binv)
#> [[1]]
#> [[1]]$eigval
#> c:  1 
#>    ───
#>    2⋅x
#> 
#> [[1]]$eigmult
#> [1] 1
#> 
#> [[1]]$eigvec
#> c: [0  1]ᵀ
#> 
#> 
#> [[2]]
#> [[2]]$eigval
#> c: 1
#>    ─
#>    x
#> 
#> [[2]]$eigmult
#> [1] 1
#> 
#> [[2]]$eigvec
#> c: ⎡-x    ⎤
#>    ⎢───  1⎥
#>    ⎣ 2    ⎦ᵀ