Edit me

Introduction

Although you can substitute symbolic variables with numerical values to get a particular numerical result from a symbolic expression, the process of doing substitution is slow and inefficient. The best way to use these symbolic expressions in the Matlab’s numerical calculation is exporting them as C++ source code and compile them as MEX binaries (or use it on other C++ projects directly).

When exporting to C++ code, the original expression will be first optimized using Common Subexpression Elimination (CSE) techniques, and then export to C++ files based on the given template.

There are two ways to export a SymExpression object:

  • using export method of SymExpression class directly;
  • create a wrapper SymFunction object first and then use export method of SymFunction class.

The first one is straightforward, but needs to provide many information at exporting. The second approach stores some information at initiating the SymFunction object, hence, less information is needed at exporting.

Using export Method

The basic syntax of exporting would looks like this:

export(expr,'Param1','Value1',...);

where Param1 and Value1 is a pair of parameter-value (as of graphic commands in Matlab):

The following two parameters must be provided:

  • Vars : the list of symbolic variables.
  • File : the full path of the file to be exported to
>> a = SymVariable('a'); 
>> b = SymVariable('b');
>> b_vec = SymVaraible('var',[3,1]);
>> expr = tomatrix((b*(a+b)).^2) * b_vec;
>> export(expr,'Vars',{a,b,b_vec},'File','test'); % expr is from the previous example
Compiling: test.cc	Elapsed time is 0.321564 seconds.

To use the exported function, the order and dimensions of input arguments must match the order in Vars.

>> test(1,2,[3,4,5])

ans =

   108
   144
   180

There are some optional parameters for different type of operations:

  • ForceExport: If false and the same file already exists, then the export process will be skipped with warning. However, if this option set to be true, then it will be exported regardless of the previous status. Default: false
  • BuildMex: If true, the exported C++ source code will be compiled as MEX binary so that can be used directly in Matlab. Default: true
  • Namespace: The exported function can be defined as a specific Namespace. Default: SymExpression
  • TemplateFile: The template file for the C++ source code. If empty, then use the default template file comes with FROST. Default: []
  • TemplateHeader: The template file for the C++ header file. If empty, then use the default template file comes with FROST. Default: []

Use SymFunction Wrapper Class

Creating SymFunction Objects

The main advantage of using SymFunction is to store the required information (Namely, Vars and File) as initialization. In addition, you can compute the first and second order partial derivatives (Jacobian and Hessian) with respect to the dependent variables. In particular, the SymFunction separate dependent symbolic variables in two main catagories: variables and parameters. The automatic partial derivatives will be only computed with respect to variables; parameters will be considered constants.

To initialize a SymFunction object, run:

>> func = SymFunction('test', expr, {b_vec}, {a,b});

Here, the function name of the symbolic expression expr is 'test', the dependent variable is b_vec and parameters are a and b.

Exporting SymFunction Objects

Exporting a SymFunction object is much easier:

>> export(func, export_path); % export_path is some path to be exported

To call the exported function (MEX) in Matlab, the orders and dimensions of input arguments should matches the orders and dimensions of variables and parameters (variables first), e.g.,

>> test([3,4,5],1,2)

ans =

   108
   144
   180
>> sqrt(func)

ans =

{{Sqrt[b^2*(a + b)^2*var$1$1]}, {Sqrt[b^2*(a + b)^2*var$2$1]}, {Sqrt[b^2*(a + b)^2*var$3$1]}}

Exporting Jacobian and Hessian of Symbolic Expression

With SymFunction, users can directly export the first order partial derivatives (Jacobian) and the second order partial derivatives (Hessian) of the symbolic expression using exportJacobian and exportHessian methods.

Exporting Jacobian

When exporting the Jacobian matrix, the method export two functions: one with prefix “J_” and another with prefix “Js_”. For example:

>> exportJacobian(func,pwd); % pwd is the current directory
Compiling: J_test.cc	Elapsed time is 0.239276 seconds.
Compiling: Js_test.cc	Elapsed time is 0.205092 seconds.

Where “Js_test” returns the indices of non-zero entries of the sparse Jacobian matrix, and “J_test” returns the values of non-zero entries. To construct the actual Jacobian matrix:

>> idx = Js_test(0);
>> val = J_test([1,2,3],1,2);
>> jac_sparse = sparse(idx(:,1),idx(:,2),val);
>> jac_full = full(jac_sparse)

jac_full =

    36     0     0
     0    36     0
     0     0    36

Exporting Hessian

When exporting the Hessian matrix, the method export two functions: one with prefix “H_” and another with prefix “Hs_”.

>> exportHessian(func,pwd);
Compiling: H_test.cc	Elapsed time is 0.211086 seconds.
Compiling: Hs_test.cc	Elapsed time is 0.201248 seconds.

Similarly, “Hs_test” returns the indices of non-zero entries of the sparse Hessian matrix, and “H_test” returns the values of non-zero entries.

To call “H_test”, the last argument must be the weights lambda, e.g.,

idx = Hs_test(0);
val = H_test([1,2,3],1,2,[1,10,100]);
Tags: symbolic