TOMLAB Appendix C

From TomWiki
Jump to navigationJump to search

Notice.png

This page is part of the TOMLAB Manual. See TOMLAB Manual.

TomSym - the Modeling Engine

This appendix describes the details and functions of relevance to the user when modeling optimization and optimal control problems with TomSym. It is possible to solve the modeling problems, either with ezsolve or by converting the problem to a standard TOMLAB Prob struct with sym2prob. The latter provides for the option of controlling all solver settings per the TOMLAB standard (see the solver manuals for more information). The procedure for using MAD (Matlab Automatic Differentiation) is also described in the sections below.

Main functions

The following Matlab functions are used directly by the user when modeling problems for processing by the TOMLAB solvers.

tom - Generate a tomSym symbol

x = tom creates a scalar tomSym  symbol with  an automatic name. 
x = tom(label)  creates a scalar symbol with  the  provided name. 
x = tom(label,m,n)  creates a m-by-n matrix  symbol.
x = tom([],m,n)  creates a matrix symbol with  an automatic name. 
x = tom(label,m,n,'int') creates an integer  matrix symbol.
x = tom(label,m,n,'symmetric')  creates a symmetric  matrix  symbol.

Because constructs like "x = tom('x')" are very common, there is the shorthand notation "toms x". See also: toms, tomSym

toms - Create tomSym objects

Toms is a shorthand notation, possibly replacing several calls to 'tom'.

A symbol is created in the current workspace for each name listed. If a size is specified on the format "NxM" where N and M are integers, then all subsequent symbols will get that size. If the size specification ends with an exclamation point (as in "3x4!") then a symbolic array of concatenated scalar symbols is created instead of one matrix symbol.

The flags "integer" (or "int") and "symmetric" are recognized. If a flag is encountered, then all subsequent symbols will get the properties of that flag.

-integer: The variable is constrained to integer values, resulting in a

mixed-integer problem  (which  requires a compatible solver.)

-symmetric: The variable is symmetric, so that x' == x. This requires that

the  dimensions  be square. An NxN symmetric matrix only contains 
N*(N+1)/2  unknowns, and the resulting symbolic object uses the 
setSymmetric  function.

Examples:

toms x y z
is  equivalent to 
x = tom('x');
y = tom('z');
z = tom('z');

toms 2x3 Q 3x3 -integer R -symmetric S
is  equivalent to
Q  = tom('Q', 2,  3);
R  = tom('R', 3,  3,  'integer');
S  = tom('S', 3,  3,  'integer',  'symmetric')

toms 3x1!  v
is  equivalent to 
v1 = tom('v1'); 
v2 = tom('v2'); 
v3 = tom('v3'); 
v = [v1;v2;v3];

In the last example, with the exclamation point, the result is a vector containing scalar symbols. This works differently from the matrix symbols used in the previous examples. Mathematically this v is equivalent to "toms 3x1 v", but the auto-generated code will be different. Expressions such as v(1)+sin(v(2))*v(3) will be more efficient, while expressions such as A*v will be less efficient.

Note: While the "toms" shorthand is very convenient to use prototyping code, it is recommended to only use the longhand "tom" notation for production code. The reason is that Matlab's internal compiler tries to guess whether a statement like "x(1)" is an index into a vector or a call to a function. Since it does not realize that the call to "toms" creates new variables is will make the wrong guess if that function (named "x" in this example) is on the Matlab path when the script is loaded into memory. This will cause strange and unexpected results.

See also: tom, tomSym, setSymmetric

tomSym/tomSym - Class constructor

NOTE: Use toms or tom to create tomSym symbols.

p = tomSym(a,m,n,arguments...) creates a tomSym  using  the  operator a. 
p = tomSym(const)  creates a tomSym  constant with  the  value  const.
p = tomSym(struct) converts a struct into a tomSym, if the  struct has the required fields.

See also: toms, tom, tomSym/funcs, tomSym/tomSym

ezsolve - Solve a tomSym optimization problem

[solution, result] = ezsolve(f,c) returns the solution to the minimization problem that is defined by the objective function f and the constraints c. The result structure from tomRun is provided in a second output argument.

Ezsolve can also be used to find least-square solutions to equations. If options.norm is set to 'L2', then f can be a set of equations. (If there are equations both in f and c, then the ones in c are considered as strict, and will be solved to tolerances, while the ones in f are solved in a least-square sense. If f is a vector, then the L2 norm of f is minimized.

Ezsolve is meant to be as simple to use as possible. It automatically determines the problem type and finds a suitable solver.

The returned solution is a struct, where the fields represent the unknown variables. This struct can be used by subs to convert a tomSym to a numeric value.

s = ezsolve(f,c,x0) uses the initial guess x0. The input argument x0 can be a struct containing fields names as the unknown symbols, for example a previously returned solution. Alternatively, x0 can be a cell array of simple tomSym equation that can be converted to a struct using tom2struct.

s = ezsolve(f,c,x0,name) sets the problem name.

s = ezsolve(f,c,x0,OPTIONS) where OPTIONS is a structure sets solver options. The options structure can have the following fields.

OPTIONS.name - The name  of  the  problem
OPTIONS.type - The problem  type, e.g. 'lp', 'qp', 'con', ... 
OPTIONS.solver	- The solver to  use,  e.g. 'snopt', 'knitro',  ... 
OPTIONS.prilev 	- The ezsolve  and tomRun  print  level (default 1) 
OPTIONS.use_d2c  - (boolean) true = compute symbolic  d2c 
OPTIONS.use_H	- (boolean) true = compute symbolic  H

See also: tomDiagnose, sym2prob, tomRun

sym2prob - Compile symbolic function/constraints into a Prob struct

Prob = sym2prob(type,f,c) creates a Prob structure, suitable for tomRun, with the objective of minimizing f, subject to c, with respect to all symbols that they contain.

The problem type can be (among others):

'lp' 	- Linear   programming
'qp'	- Quadratic programming
'con'	- Nonlinear programming
'qpcon' - Quadratic problem  with  nonlinear constraints
'minlp' - Mixed integer nonlinear programming
'sdp'	- Linear   semidefinite programming
'bmi'	- Bilinear semidefinite programming

Prob = sym2prob(f,c) calls tomDiagnose to attempt to guess the problem type, and prints a warning.

The objective f must be a tomSym symbolic object, while the constraints list c should be a cell array.

If the objective f is a vector or matrix, then a least-square problem is solved, minimizing 0.5*sum(vec(f)) (Half the sum-of-squares of the elements of f ). If f is an equality on the form lhs == rhs, then the sum-of-squares of the difference (rhs-lhs) is minimized.

sym2prob(type,f,c,x0) supplies an initial guess for one or more of the unknowns. The guess x0 should be a struct, where each field is named as a symbol and contains a numeric array of the correct size.

sym2prob(type,f,c,x0,OPTIONS) where OPTIONS is a structure sets options. The options structure can have the following fields.

OPTIONS.name	- The name  of  the  problem 
OPTIONS.use_d2c  - (boolean) true = compute symbolic  d2c 
OPTIONS.use_H	- (boolean) true = compute symbolic  H

Linear and box constraints will be automatically detected, if they are formulated using simple addition and multiplication. For example,

-3*(x+2) <= 4+x

is automatically converted to

x >= -2.5

For nonlinear problems, sym2prob will generate temporary m-files representing the nonlinear functions and their derivatives (These files are usually small and harmless, and many modern operating systems automatically clean up old temporary files). In order to remove these files when they are no longer needed, it is recommended to run tomCleanup(Prob) after the problem has been solved.

Overloaded  methods:
    tomSym/sym2prob

getSolution - Extract variables from a solution retuned by tomRun

s = getSolution(solution) returns a struct where each field corresponds to one of the symbols used in the tomSym problem formulation.

tomDiagnose - Determine the type for of tomSym optimization problem

type = tomDiagnose(f,c) returns a text string, defining the problem type that is represented by the objective function f and the constraints c.

Some possible return values:

'lp' 	- Linear   programming
'qp'	- Quadratic programming
'cls'	- Least  squares  with  linear constraints
'nls'	- Nonlinear least  squares
'con'	- Nonlinear programming
'qpcon' - Quadratic problem  with  nonlinear constraints
'minlp' - Mixed integer nonlinear programming
'sdp'	- Linear   semidefinite programming
'bmi'	- Bilinear semidefinite programming

The objective f must be a tomSym symbolic object, while the constraints list c should be a cell array of tomSym objects.

tomCleanup - Remove any temporary files created for a tomSym problem.

tomCleanup(Prob) removes any temporary files (created by sym2prob) that are referenced in the problem structure Prob. This should be done after a problem has been solved, to avoid leaving garbage in the system's "temp" directory (although most modern operating system will clean up these files eventually anyway.)

WARNING: IF THE AUTOGENERATED FILES HAVE BEEN EDITED, THEN RUNNING

TOMCLEANUP WILL CAUSE ALL CHANGES TO BE LOST.

tomCleanup('all') will remove all files and directories that are judged to be tomSym files from the system's "temp" directory. All files that contain a certain "marker" in the filename will be removed. This might be useful if a large number of temporary files were created accidentally, such as when running sym2prob inside a for-loop without calling tomCleanup(Prob) at the end of the loop.

Note: Under normal circumstances there is never a need to run

tomCleanup('all'). The operating system should remove old temporary
files as required.

After running tomCleanup, all Prob structures that reference the deleted files will be useless. See also: sym2prob

Using MAD

Some models require the use of alternative method for partial derivatives. If TomSym cannot be used, one alternative is to use MAD.

madWrap - Compute a Jacobian using MAD.

J = madWrap(FUN,N,...) uses MAD to call FUN(...) and returns the Jacobian matrix with respect to the N:th input argument.

FUN must be the name of an existing function. N must be an integer between one and nargin(FUN).

J = madWrap(M,FUN,N,...) computes the Jacobian matrix of the Mth output argument, instead of the first one.

J will be a Jacobian matrix on the form that is used by tomSym.

Sub function details

Advanced users may need to understand how and what some sub functions execute in TomSym. This section describes how to add functionality to TomSym and some more details "under the hood".

ifThenElse - Smoothened if/then/else.

y = ifThenElse(cmp1, op, cmp2, yTrue, yFalse, s) replicates the behavior of the C-language construction y = ( condition ? yTrue : yFalse ) but with a smoothing sigmoid function, scaled by s. (Setting s=0 gives discontinuous "standard" if-then-else.)

The operand string op must be the name of one of the comparison operators ('eq', 'lt', 'le', etc.)

Example: The absolute value of x is ifThenElse(x,'gt',0,x,-x)

Overloaded  methods:
   tomSym/ifThenElse

tomSym/derivative

The symbolic derivative of a tomSym object.

df_dx = derivative(f,x) computes the derivative of a tomSym object f with respect to a symbol x.

d2f_dxdy = derivative(f,x,y,..) computes the second (third, ...) derivative of f with respect to the symbols x, y, ...

Both f and x can be matrices.

The symbol x can either be a tomSym symbol, or a concatenation of tomSym symbols.

There exist several conventions for how the elements are arranged in the derivative of a matrix. This function uses the convention that vec(df) = df_dx*vec(dx). This means that if size(f) = [m n] and size(x) = [p q] then size(df_dx) = [m*n, p*q]. Thus, the derivative of a matrix or vector with respect to a scalar is a column vector, the derivative of a scalar is a row vector, and the derivative of any matrix with respect to itself is an identity matrix.

Examples:

  • If f and x are vectors, then J = derivative(f,x) computes the Jacobian matrix.
  • If f is scalar and x is a vector, then H = derivative(f,x,x) computes the Hessian matrix.

For functions that tomSym/derivative is unfamiliar with, it assumes that there also exists a derivative function for each argument. For example, when computing the derivative of a function "userfun", it is assumed that "userfunJ1" gives the derivative of userfun with respect to its first input argument. Reference: Brookes, M., "The Matrix Reference Manual"

http://www.ee.ic.ac.uk/hp/staff/dmb/matrix/intro.html

ppderivative - The derivative of a piecewise polynomial.

dpp = ppderivative(pp) returns a piecewise polynomial which is the derivative of pp, except at points where pp is discontinuous.

dpp = ppderivative(pp,n) returns the nth derivative. A negative n results in the antiderivative (integral) of pp.

tomSym/mcode

Generate m-code from a tomSym object.

[code, data, header] = mcode(f) generates m-code, representing an object f.

All constants are moved to a data object, which needs to be supplied in the function call.

The returned function header lists all symbols alphabetically, and the data input last.