rsymbolic-mathmaxima

Inline code example for using the symbolic code "maxima" in R (via the package "rim")


Does anybody have a worked example for using the package "rim" to run maxima in R with inline code (not RMarkdown)? We currently use maxima in a modelling class, and it would be great to allow students to explore equations symbolically in R. They could then do all numerical work in R (plotting etc.), but call maxima for the analytical pieces.

Thank you for any tips!

For example, some of this code works and some doesn't:

library(rim)
myeqn <- maxima.get("solve((1 + r*(1 - x/K))*x = x, x);")

myint <- maxima.get("integrate(1/(1-x), x);")
df <- data.frame(x = seq(0, 1, by = 0.1))
maxima.eval(myint, code = TRUE, envir = df)

mymat <- maxima.get("matrix([0, 1, a], [1, 0, 1], [1, 1, 0]);")
maxima.get("determinant(mymat);") # Doesn't work
maxima.get("determinant(%o12);") # Does work, using the right output line number for mymat

I would love to see more worked examples of how to go back and forth between R and maxima on the command line.


Solution

  • I don't know if this helps, but I think I can see what the problem is. As far as I can tell, the symbol mymat (for example) is only defined on the R side of the interface; Maxima only knows about the %o12 variable.

    It's possible that some of these solutions are re-inventing the wheel (the package isn't extremely thoroughly documented ...)

    assign symbols on the maxima side

    If you use the colon operator in your Maxima call, that will assign a persistent label in the Maxima session:

    mymat <- maxima.get("mymat: matrix([0, 1, a], [1, 0, 1], [1, 1, 0]);")
    maxima.get("determinant(mymat);")
    

    You can make this slightly less painful/more magical by defining a "Maxima assignment" operator which evaluates the expression in Maxima, assigns it to a Maxima symbol, and also assigns it to an R symbol:

    "%<-%" <- function(symbol, expr) {
        sstring <- deparse(substitute(symbol))
        res <- maxima.get(sprintf("%s: %s", sstring, expr))
        assign(sstring, res, parent.frame())
        return(invisible(res))
    }
    
    newmat %<-% "matrix([0, 1, a], [1, 0, 1], [1, 1, 0]);"
    maxima.get("determinant(newmat)")
    

    hacking

    Alternatively (this is what I tried before I came up with the better ideas above), you can construct a table of Maxima objects that are known to R and substitute their "%o" names in a string before passing them to Maxima:

    maxima_symbol_tab <- function() {
        max_objects <- list()
        for (n in ls(.GlobalEnv)) {
            if (inherits(obj <- get(n), "maxima")) {
                max_objects <- c(max_objects, list(c(name = n, matname = attr(obj, "output.label"))))
            }
        }
        as.data.frame(do.call(rbind, max_objects))
    }
    
    mtab <- maxima_symbol_tab()
    maxima.sub <- function(string) {
        for (i in seq(nrow(mtab))) {
            ## cat(string, mtab$name[i], mtab$matname[i], "\n")
            string <- gsub(mtab$name[i], mtab$matname[i], string, fixed = TRUE)
        }
        return(string)
    }
    
    maxima.get(maxima.sub("determinant(mymat);"))