The definition and the use of External Functions (thereafter — functions) complies with the following rules:
1. | User can define his/her own functions and use them in an optimization problem. |
2. | The total number of function arguments should not exceed 16. |
3. | The total number of symbols in the function description should not exceed 128. |
4. | The function name must begin with the prefix fnext_. |
5. | The function definition can include only legal symbols (ref. to the definition of legal symbols in the PSG Help). |
6. | Functions must return a scalar value. |
7. | User should define for each function the corresponding gradient function, with the same name and arguments set. |
8. | The gradient function name must begin with the prefix grext_. For example, the fnext_myfunction(arg1, arg2, arg3) function must have the corresponding grext_myfunction(arg1, arg2, arg3) function for gradient calculation. |
9. | The gradient function must return a vector value, with dimension equals to the number of variables (not arguments) on which the function is defined. |
10. | External Function and its gradient must be implemented in different m-files that have the name (after an appropriate prefix) coinciding with the name of the function and its gradient. |
11. | The function and its gradient must have the same list of arguments. |
12. | The arguments types are legal MATLAB data types. |
13. | Only variables of the problem can be used as arguments of the functions (numerical values are not allowed) |
14. | All function arguments must be defined before calling the optimization procedure. |
15. | Argument names are case sensitive. |
16. | The first function argument must be a string with the tab separated list of variables names, on which the function is defined. |
17. | The second function argument must be a real vector (row vector or column vector) of components ordered as the sequence of the variables passed as the first argument. The second argument is a variable point at which the value of the function is calculated during the optimization. The actual value of this point must correspond to the function and its gradient definition domain. |
18. | The problem statement (see Problem Statement Description in MATLAB) must include the complete function definition (with its three arguments). |
19. | External functions (and their linear combinations) can be specified in the objective and constraints. |
20. | External functions can be used by the PSG functions tbpsg_run, riskprog and riskconstrprog for solving the optimization problems. |
Example. Formal Problem Statement
Minimizing
subject to
box constraints
To solve the problem we created files fnext_polynom_m.m and grext_polynom_m.m (in the folder .\Aorda\PSG\MATLAB\Examples\Problems\) containing function code:
function [value] = fnext_polynom_m(headerpoint, valuespoint, matrix_A)
D = length(valuespoint);
if (size(matrix_A, 1) ~= D) || (size(matrix_A, 2) ~= D)
error('Wrong sizes of matrix_A');
end
value = 0.0;
for i = 1:D
for j = 1:D
value = value + matrix_A(i, j)*valuespoint(i)*valuespoint(j);
end
value = value + valuespoint(i)^4;
end
end
and gradient code:
function [grvalue] = grext_polynom_m(headerpoint, valuespoint, matrix_A)
D = length(valuespoint);
if (size(matrix_A, 1) ~= D) || (size(matrix_A, 2) ~= D)
error('Wrong sizes of matrix_A');
end
grvalue = zeros(1, D);
for i = 1:D
for j = 1:D
grvalue(i) = grvalue(i) + matrix_A(i, j)*valuespoint(j);
end
grvalue(i) = grvalue(i) + 4*valuespoint(i)^3;
end
end
Solving the problem using mpsg_solver function
Run the following example from the folder ./Aorda/PSG/MATLAB/Examples/Problems/External_Function_test.m or type the next code in MATLAB:
Define problem dimension:
D = 5;
Create the tab separated list of variables names (x1..xD):
headerpoint = ['x1' sprintf('\tx%d', 2:D)];
Create row vector for verifying calculation of the function and the gradient:
thispoint = ones(1, D);
Define the matrix on which the function and the gradient are calculated:
A = eye(D);
for i=1:D-1
A(i, i+1) = 1.0/(10.0+D);
A(i+1, i) = A(i, i+1);
end
Define the matrix on which the constraint is defined:
headermatrix = ['id' sprintf('\t%s', headerpoint)];
matrix_linear = ones(1, D+1);
Specify the problem description:
problem_statement = sprintf('%s\n',...
'Problem: problem_test, type = minimize',...
'Objective: objective_external_function',...
'fnext_polynom_m(headerpoint, thispoint, A)',...
'Constraint: constraint_linear, lower_bound = 0, upper_bound = 0',...
'linear_balance(matrix_linear)',...
'Box_of_Variables: lowerbounds = -1, upperbounds = 1',...
'Solver: TANK, precision = 9');
Pack the matrix_linear matrix into the structure array defining the initial data using tbpsg_matrix_pack:
count = 1;
toolboxstruc_arr(count) = tbpsg_matrix_pack('matrix_linear', matrix_linear, headermatrix);
Solve the problem using tbpsg_run:
[solution_str, outargstruc_arr] = tbpsg_run(problem_statement, toolboxstruc_arr);
Output:
fprintf('Solution status: %s\n%s\nOptimal point:\n', get_solution(solution_str, outargstruc_arr, 'solution_status'), ...
get_solution(solution_str, outargstruc_arr, 'objective'));
optimal_point = get_optimalpoint(solution_str, iargstruc_arr, outargstruc_arr);
for i=1:D
fprintf('%s\t=\t%f\n', optimal_point{i, 1}, optimal_point{i, 2});
end
After running the function the following messages are displayed:
mpsg_solver function using:
Reading problem formulation
Reading fnext_polynom_m(headerpoint, thispoint, a)
Reading matrix_linear
16.7% of scenarios is processed
Start optimization
Ext.iteration=7 Objective=0.000000000000E+00 Residual=0.000000000000E+00
Optimization was stopped
Solution is optimal
Calculating resulting outputs. Writing solution.
Solver has normally finished. Solution was saved.
Solution status: optimal
objective_external_function = 0
Optimal point:
x1 = 0.000000
x2 = 0.000000
x3 = 0.000000
x4 = 0.000000
x5 = 0.000000
Solving the problem using riskprog function
We can solve the same problem using riskprog function (see riskprog).
[xout, fval, status] = riskprog('fnext_polynom_m(headerpoint, thispoint, A)', ...
[], [], [], [], [], [], [], matrix_linear(1, 2:end), 0, -1, 1);
The first argument of the riskprog function is the complete function description defining the objective function (the string 'fnext_polynom_m(headerpoint, thispoint, A)').
Since the risk function is an External Function, parameters w, H, c, p, d are not defined and should be omitted (defined as []).
The problem does not have equality constraints, thus parameters A and b are omitted.
As Aeq we substitute the matrix_linear matrix defined before (without the first column where id is defined). The matrix_linear defined above is the matrix of coefficients for the inequality constraints. The first column of this matrix, which represents the 'id" column, is not needed in the riskprog function.
The right-hand side of the inequality constraints is defined as 'null' vector.
Box constraints are specified as -1 and 1 for all the components of the solution vector.
After running the function the following messages are displayed:
riskprog function using:
Solution status: optimal
Objective = 0.000000
Optimal point:
x1 = 0.000000
x2 = 0.000000
x3 = 0.000000
x4 = 0.000000
x5 = 0.000000
In a similar way, External Functions can be used in the riskconstrprog function (see riskconstrprog).