--- title: "The high-level (symbol) interface" author: "Mikkel Meyer Andersen and Søren Højsgaard" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{The high-level (symbol) interface} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) ``` ```{r, message=FALSE} library(Ryacas) ``` A short summary of often-used `yacas` commands are found in the section "`yacas` reference" in the "Getting started" vignette. A short summary of `Ryacas`'s high-level functions are found in the section "`Ryacas` high-level reference" at the end of this document. # Introduction Start with a base symbol what can either be: * A `yacas` command, e.g. `x`, `2*a` or something similar * An `R` matrix or vector. Here, we keep it simple. ```{r} x <- ysym("x") 2*x^2 - 5 c(-2, 5)*x c(2*x, -x^3) as_r(c(-2, 5)*x) # or yac_expr(c(-2, 5)*x) ``` Then consider an `R` matrix and vector: ```{r} A <- outer(0:3, 1:4, "-") + diag(2:5) a <- 1:4 A a ``` They are now considered `yacas`-enabled: ```{r} B <- ysym(A) B as_r(B) b <- ysym(a) b as_r(b) ``` Notice how they are printed using `yacas`'s syntax. We can apply `yacas` functions using `y_fn()`: ```{r} y_fn(B, "Transpose") y_fn(B, "Inverse") y_fn(B, "Trace") ``` Standard `R` commands are available (see the section "`Ryacas` high-level reference" at the end of this document): ```{r} A %*% a B %*% b t(A) t(B) exp(B) as_r(exp(B)) A[, 2:3] B[, 2:3] A[upper.tri(A)] <- 1 B[upper.tri(B)] <- 1 A B 2*A - A 2*B - B A %*% solve(A) B %*% solve(B) solve(A %*% t(A)) solve(B %*% t(B)) solve(A, a) solve(B, b) ``` We can also assign a `yacas` variable, but remember that this may be difficult to distinguish: ```{r} yac_str("W") # Get variable W if exists, or else just a symbol yac_str("Variables()") # ...or list variables B yac_assign(B, "W") # assign B in R to W in yacas yac_str("W") # Get variable W if exists, or else just a symbol yac_str("Variables()") # ...or list variables yac_silent("Clear(W)") yac_str("Variables()") # List variables yac_str("W") # Get variable W if exists, or else just a symbol ``` # Simplify and output to TeX There are additional functions available: * `simplify()` * `tex()` To demonstrate these and some additional benefit, we exploit `yacas`'s symbolic availabilities. ```{r} D <- diag(4) %>% ysym() D D <- D/2 D D[2:3, 1] <- "d" D[3, 4] <- "2*d + 2" D D %>% solve() D %>% solve() %>% simplify() D %>% solve() %>% simplify() %>% tex() ``` \[ `r D %>% solve() %>% simplify() %>% tex()` \] `yacas` has a `Simplify()` function. This is made available via a `simplify()` function that also includes a time-out that prevents `yacas` in making the `R` session hang, but it requires that the `unix` package is available. The default `timeout` value used when `unix` is available is `2` seconds. # Derivatives We illustrate using the example in : ```{r} L <- ysym("x^2 * (y/4) - a*(3*x + 3*y/2 - 45)") L ``` We can consider one variable only: ```{r} deriv(L, "x") Hessian(L, "x") ``` Or multiple variables: ```{r} deriv(L, c("x", "y", "a")) H <- Hessian(L, c("x", "y", "a")) H as_r(H) eval(as_r(H), list(x = 2, y = 2, a = 2)) ``` The Jacobian is taken on a vector function denoted by many functions: ```{r} L2 <- ysym(c("x^2 * (y/4) - a*(3*x + 3*y/2 - 45)", "x^3 + 4*a^2")) # just some function L2 Jacobian(L2, "x") Jacobian(L2, c("x", "y", "a")) ``` # Solving equations Say we want to find roots of a polynomial. We use the generic `solve(a, b, ...)` function. Note the conventions are as follows: * Linear system of equations (works as `R`'s `solve()` as demonstrated above): + When `a` is a matrix and `b` not provided, this finds the inverse of `a`. + When `a` is a matrix and a vector `b` is provided, the linear system of equations is solved. * Else: + `solve(a, b)`: find roots of `a` for variable `b`, i.e. yacas `Solve(a == 0, b)` + `solve(a, b, v)`: find solutions to `a == b` for variable `v`, i.e. yacas `Solve(a == b, v)` ```{r} xs <- ysym("x") poly <- xs^2 - xs - 6 poly zeroes <- solve(poly, "x") # Solve(x^2 - x - 6 == 0, x) zeroes tex(zeroes) zeroes %>% y_rmvars() ``` We can also find values of `x` where the polynomial equals another constant. If we were working with strings via the low-level interface it would be easy via `paste()`, but as we are working with `ysym()`'s we use the `solve()` function directly: ```{r} solve(poly, 3, "x") # Solve(x^2 - x - 6 == 3, x) solve(poly, 3, "x") %>% tex() ``` \[ `r solve(poly, 3, "x") %>% tex()` \] ## Solving a system of equations ```{r} x <- ysym("x") y <- ysym("y") lhs <- c(3*x*y - y, x) rhs <- c(-5*x, y+4) ``` $$\begin{align} `r tex(lhs[[1]])` &= `r tex(rhs[[1]])` \\ `r tex(lhs[[2]])` &= `r tex(rhs[[2]])` \end{align}$$ ```{r} sol <- solve(lhs, rhs, c("x", "y")) sol sol_vals <- lapply(seq_len(nrow(sol)), function(sol_no) { y_rmvars(sol[sol_no, ]) }) sol_vals sol_envir <- lapply(sol_vals, function(l) { list(x = as_r(l[1]), y = as_r(l[2])) }) sol_envir do.call(rbind, lapply(seq_along(sol_envir), function(sol_no) { sol_val <- sol_envir[[sol_no]] data.frame(sol_no = sol_no, eq_no = seq_along(sol_val), lhs = eval(as_r(lhs), sol_val), rhs = eval(as_r(rhs), sol_val)) })) ``` # `Ryacas` high-level reference Principle: * `ysym(x)` converts `x` to a `yac_symbol` that automatically runs `yacas` when needed. `x` can both be a text string with `yacas` commands or an `R` vector/matrix. * `as_r(x)`: Is used to convert the `yac_symbol` back to an `R` representation. * `y_fn(x, fn, ...)`: Apply a `yacas` function `fn` to the `yac_symbol` `x`, i.e. `fn(x, ...)`; note that this is evaluated immediately when `x` is a `yac_symbol` as opposed to when `x` is a string Reference: The following functions work with `yac_symbol`s. * `ysym()`: Create `yac_symbol` + `ysym_make()`: Make a vector of `yac_symbol`s + `ysym_ls()`: List declared `yac_symbol`s * `yac_*()` functions (see the "Getting started" vignette) + `yac_str()`: Return `yacas` string + `yac_expr()`: Return `R` expression + `yac_silent()`: Do something silently + `yac_assign()`: Assign a variable * Other + `simplify(x, timeout = 2)`: Try `yacas`'s `Simplify()` function. When the `unix` package is available, the `timeout` (in seconds), stops trying after that amount of time to avoid making the `R` process hang. + `tex()`: Convert + `y_fn(x, fn, ...)`: Apply a `yacas` function `fn` to the `yac_symbol` `x`, i.e. `fn(x, ...)` + `y_rmvars(x)`: Remove variable names in `x` + Derivatives: - `deriv(expr, vars)`: takes derivative of `yac_symbol` `expr` with respect to `vars` - `Jacobian(expr, vars)`: finds Jacobian of `yac_symbol` `expr` (usually a vector of expressions) with respect to `vars` - `Hessian(expr, vars)`: finds Hessian matrix of `yac_symbol` `expr` with respect to `vars` + Other - `lim()` * Standard `R` that has been implemented for `yac_symbol`s: + `print()` + `c()` + `dim()` + `cbind()` + `rbind()` + `[` getter + `[<-` setter + `[[` getter + `%*%` matrix/vector multiplication + `diag()` getter + `diag<-()` setter + `upper.tri()` getter + `lower.tri()` getter + `t()` + `solve()` (see above and in help page) + `integrate()` + `sum()` + `prod()` + Ops: `+`, `-`, `*`, `/`, `^` + Math functions: `sin()`, `cos()`, `tan()`, `asin()`, `acos()`, `atan()`, `asinh()`, `acosh()`, `atanh()`, `exp()`, `log()`, `sqrt()`