Making new expressions

Most interaction with Coffeequate is done with the methods of the Expression object that CQ returns. An expression is implicitly equated to zero (even if it's not going to be used as an equation), so all of the following are equivalent:

CQ("y = m*x + b")
CQ("m*x + b - y = 0")
CQ("m*x + b - y")

Converting to strings

You'll want to convert your expressions into some kind of pretty, string representation at some point. There are three methods that do this:


expr.toString() converts the expression expr into a simple string representation. For example,

CQ("E = m*\\c**2").toString() // ' - E + m*c**2'


expr.toMathML() converts the expression expr into a MathML string. For example,

CQ("E = m*\\c**2").toMathML() // '<mo>-</mo><mi class="variable">E</mi><mo>+</mo><mi class="variable">m</mi><mo>&middot;</mo><msup><mi class="constant symbolic-constant">c</mi><mn class="constant">2</mn></msup>'


expr.toLaTeX() converts the expression expr into a LaTeX string. For example,

CQ("E = m*\\c**2").toLaTeX() // '-E+m \\cdot c^{2}'

Solving equations

solve(variable, equivalencies={})

expr.solve(variable) solves the expression expr for the variable variable, and assumes that the expression is equal to zero. For example,

CQ("m*x + b - y").solve("y") // m*x + b
CQ("m**2*\\c**4 + p**2*\\c**2").solve("p") // sqrt(-(c**4*m**2)), -(sqrt(-(c**4*m**2)))

expr.solve(variable, equivalencies) is the same as above, except that it takes a map of equivalencies. This equivalencies map describes which variables are equivalent to each other. For example, if x and z are equal, then equivalencies = {"x":["x", "z"], "z":["x", "z"]}. The order within the map is irrelevant, but it must be redundant.

nsolve(guess, variable, equivalencies={}, tol=1e-9, max_iterations=75)

expr.nsolve(guess, variable) finds a numerical solution of the expression expr for the the variable variable using Newton's method with the initial value guess, assuming that the expression is set to zero. This only works for differentiable expressions.

For example,

CQ("x**2 - 2").nsolve(1.5,"x") // 1.4142135623730951

The use of equivalencies is the same as for expr.solve.

expr.nsolve(guess, variable, equivalencies, tol) finds the numerical solution of the expression expr so that the difference between the found solution and the exact solution is less than tol.

expr.nsolve(guess, variable, equivalencies, tol, max_iterations) will attempt to find a numerical solution within tol for the expression expr before the maximum number of iterations allowed max_iterations is reached. If this doesn't happen, the function will throw an error:

CQ("x**2 + 7").nsolve(1.5,"x") // Error: Maximum Number of Iterations Reached

Simplifying expressions


expr.simplify() simplifies the expression expr if possible. It can optionally take an equivalencies map like solve, which it will use to simplify the equation further.


expr.expand() expands the expression expr if possible.

Substituting values

sub(subs, equivs={}, subUncertainties=false, evalSymConstants=false)

expr.sub(subs) substitutes values into variables in expr according to the map subs. subs maps variable labels to values that should be substituted in their place. Values should be either numbers or Coffeequate expressions. For example,

CQ("E = m*\\c**2").sub({"m": 10}) // -E + 10*\\c**2

Much like simplify and solve, sub can take an equivs argument mapping variables to an array of equivalent variables. This will be used while substituting and subsequently simplifying.

There are two optional boolean arguments, subUncertainties and evalSymConstants. If subUncertainties is true, then instead of substituting values into variables, sub will substitute values into the associated uncertainties. For more information on this, see the documentation for uncertainties. If evalSymConstants is true, then symbolic constants will have their values substituted:

CQ("E = m*\\c**2").sub({"m": 10}, {}, false, true) // 898755178736817700 - E

Checking equality

equals(other, equivalencies={})

a.equals(b) returns true if a and b represent the same expression, and false otherwise.


expr.approx() sets all variables to 0 and evaluates the resulting expression, returning a number. This evaluates symbolic constants, too.

Manipulating variables


A list of variables in the expression can be retrieved with expr.getAllVariables(). For example,

CQ("E = m*\\c**2").getAllVariables() // [ 'E', 'm' ]


expr.mapOverVariables(f) applies a function f to all variables in the expression. This is useful for changing labels, for example:

var changeLabel = function(variable) {
    variable.label += "s";
    return variable;
var newExpr = CQ("E = m*\\c**2").mapOverVariables(changeLabel); // Es = ms*\\c**2

This method does not change the original expression.

Deep-copying expressions


The whole expression can be deep-copied with expr.copy(). The copy will be completely separate from the original, so it can be changed without mutating the original.

Manipulating uncertainties


expr.getUncertainty() propagates uncertainties through expr and returns a new expression representing the uncertainty in expr. For example,

CQ("m*\\c**2").getUncertainty() // sqrt(\\c**4*σ(m)**2)

Uncertainties can be substituted in using expr.sub, with the subUncertainties argument set to true.

CQ("m*\\c**2").getUncertainty().sub({m: 1}, {}, true).approx() // 89875517873681760


differentiate(variable, equivalencies={})

expr.differentiate(variable) differentiates expr with respect to variable and returns the result. For example,

CQ("a*x**2 + b*x + c").differentiate("x") // b + 2*a*x

At the moment, this only does simple derivatives, e.g. trying to differentiate 2**x will fail.

Converting to functions

toFunction(variables..., equivalencies={})

Expressions can be converted to functions using expr.toFunction(variables...), which takes some number of variable labels and returns a function that takes those same variables as arguments and returns a value or expression. For example,

var f = CQ("a*x**2 + b*x + c - y").toFunction("x", "y");
f(3, 2) // -2 + c + 3*b + 9*a