What tomSym cannot do
There are a few things that are possible in Matlab code, but which tomSym currently cannot do. Below we list the most common issues, and their work-arounds.
The size of a tomSym object cannot depend on the value of another tomSym object. This has to do with the fact that numeric solvers typically allocate memory only at the start of an optimization run, and then expect the number of unknowns to remain constant. (This may change in the future.)
Indexes into double arrays
It is not possible to use a tomSym symbol as an index into a non-tomSym array.
>> toms i >> v = [3 1 4]; >> v(i) ??? Error using ==> tomSym.subsindex at 8 Cannot use a tomSym object directly as an index (due to Matlab syntax rules). - Use lookup or submatrix instead. (See "help lookup")
For this to work, tomSym would have to intercept every array lookup (even when you are not using tomSym at all). This would slow down Matlab in general, so instead tomSym provides the lookup function. lookup(v,i) does exactly what v(i) would do if it worked.
>> lookup(v,i) ans = tomSym(1x1): lookup([3 1 4],i)
The lookup function does not have a derivative, which can be a problem if we are optimizing with respect to the lookup index. In that case, it is better to use interpolation. Interpolation also works with non-integer values for i.
>> interp1(1:3,v,i,'spline') ans = tomSym(1x1): ppval($struct,i)
Replacing values in arrays
It is not possible to change a value in an array into a tomSym expression.
>> toms x >> v = [3 1 4]; >> v(2) = x; ??? The following error occurred converting from tomSym to double: Error using ==> tomSym.double at 11 Cannot convert symbolic tomSym object to double.
When using tomSym, it is best to always create the entire vector in one operation.
>> v = [v(1) x v(2)] v = tomSym(1x3): [3 x 1]
The sparse function can be used to create a matrix that contains a lot of zeroes, but has tomSym expressions in some positions.
TomSym expressions cannot be used in if statements.
>> toms x >> if x>=0; y=x; else; y=-x; end ??? The following error occurred converting from tomSym to logical: Error using ==> logical Conversion to logical from tomSym is not possible.
This is because the if-statement is evaluated before the solver is called, so the symbolic expression has no numeric value.
The work-around is to use the ifThenElse function.
>> y = ifThenElse(x>=0,x,-x) y = tomSym(1x1): (if x>=0 then x else -x)
Note that the ifThenElse function usually has a sharply discontinuous derivative. It is therefore common that the numeric solver fails to find a solution to problems defined using this function. It may be necessary to re-write the problem in a way that is easier for the solver to handle.
N-dimensional arrays for N > 2
TOMSYM works with scalars, vectors, and two-dimensional matrices. Although Matlab can handle arrays of any dimension, TOMSYM cannot. The work-around is to use tomArray, which transforms tomSym symbols into arrays of any dimension. (TomArray also allows for a GAMS-style indexing which is a bit different from Matlab syntax, but convenient when formulating optimization problems involving high-dimension arrays.)
Note that TOMSYM supports interpn with high-dimensional numeric data, although the symbolic inputs must be of dimension less than two.
TOMSYM evaluates expressions by generating matlab code. (It does some mathematical simplification to improve efficiency, but only to a limited extent.) If an expression evaluates to 0/0 or 0*Inf, then NaN (Not a Number) will be returned. When the solver encounters a NaN, it will often just quit (although some solvers include back-tracking algorithms.)
This means that expressions such as a*log(a) can not be used if a might become zero. In this case it might be prudent to add a constraint a >= 1e-8 (or similar) to help the solver stay out of trouble.