The values of decision variables and random variables are not known when you write a model, so arithmetic on them cannot compute a number. Instead it builds an expression: a description of a quantity, which the service evaluates for every solution it considers. Expressions are written as ordinary R code, with these operators and functions:
Details
+,-,*,/and^;
Expressions need not be linear. Printing an expression shows what was built.
Expressions are vectors
A variable declared with length = 10 is an expression of length 10, and
expressions behave like numeric vectors in most ways: arithmetic works
element by element, x[3] picks one element, c() combines expressions
and numbers into a longer expression, and length() counts the elements.
There are two differences. First, the two sides of an arithmetic operation
must have the same length, or one of them length 1. R would recycle the
shorter vector, which in a model is almost always a mistake, so here it is
an error. Second, sum(), prod(), max(), min() and mean() combine
all the elements of all their arguments into one, as they do for numbers:
max(x, 0) is the largest of all the elements of x and 0, not an
element-by-element maximum, and there is no pmax(). The arguments can come
in any order, so max(0, x) works too (see summaries). mean(x) is the mean
over the elements of x; the mean over the scenarios is expectation().
Comparisons
Comparing two expressions, as in x <= y, builds a comparison rather than
returning TRUE or FALSE. What the comparison means depends on the
function it is given to: add() makes it a constraint, prob() measures
how often it holds across the scenarios, and holds() turns it into an
expression that is 1 where it holds and 0 where it does not. add() and
prob() accept <= and >=, and add() also ==; holds() accepts
all six comparisons.
What does not work
Functions not listed above, such as round(), %% and log() with a
base, stop with an error. Base R functions that are not written for
expressions do not work on them either: use variance() instead of
var(), holds() instead of ifelse(), and identical() instead of
%in% or match() to check whether two expressions are the same.
A model with max(), min() or holds() is solved by a search, so its
status is "heuristic". When every variable of such a model is an integer or a binary variable, each
needs finite bounds; a model with a continuous variable or with random
variables has no such limit. A fixed fee for using a variable at all is the exception:
written with active() on a variable declared with semi = TRUE, it keeps
a linear model exact.
Examples
m <- model()
tables <- num_var(m, "tables", lower = 0)
chairs <- num_var(m, "chairs", lower = 0)
50 * tables + 20 * chairs # an expression, not a number
#> ((50 * tables) + (20 * chairs))
tables + chairs <= 18 # a comparison, not TRUE or FALSE
#> (tables + chairs) <= 18
x <- num_var(m, "x", lower = 0, upper = 1, length = 3)
2 * x # element by element
#> [1] (2 * x[1])
#> [2] (2 * x[2])
#> [3] (2 * x[3])
sum(x) # one expression
#> (x[1] + x[2] + x[3])
max(x, 0.5) # the largest of all four
#> max(max(max(x[1], x[2]), x[3]), 0.5)