# 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    ⎦ᵀ