* Bug #13092 fixed - Optimization: check user function output
[scilab.git] / scilab / modules / optimization / macros / optimbase / optimbase_function.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 2009 - INRIA - Michael Baudin
3 // Copyright (C) 2009-2011 - DIGITEO - Michael Baudin
4 //
5 // This file must be used under the terms of the CeCILL.
6 // This source file is licensed as described in the file COPYING, which
7 // you should have received as part of this distribution.  The terms
8 // are also available at
9 // http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10
11 //
12 // optimbase_function --
13 //   Call the cost function and return the value.
14 //   If a cost function argument is defined in current object,
15 //   pass it to the function.
16 //   If an index is defined as input argument, pass it to the
17 //   function, always as second argument.
18 // Arguments
19 //   x : the point where the function is to be evaluated.
20 //   index, input : a flag to pass to the cost function
21 //      if index=1, output a message, and compute whatever is required
22 //      if index=2, compute f
23 //      if index=3, compute g
24 //      if index=4, compute f and g
25 //      if index=5, returns c
26 //      if index=6, returns f and c
27 //      if index=7, returns f, g, c and gc
28 //    where
29 //      f : the cost function
30 //      g : the gradient of the cost function
31 //      c : the nonlinear, positive constraints
32 //      gc : the gradient of the nonlinear, positive constraints
33 //    Other values of index might be used in the future,
34 //    for example, when an derivative-based optimizer with
35 //    non linear constraints is required.
36 //   index, output :
37 //     if index > 0, everything went find
38 //     if index == 0, interrupts the optimization
39 //     if index < 0, f cannot be evaluated
40 // Calling sequences :
41 //   [ this , f , index ] = optimbase_function ( this , x , index )
42 //   [ this , f , g , index ] = optimbase_function ( this , x , index )
43 //   [ this , f , c , index ] = optimbase_function ( this , x , index )
44 //   [ this , f , g , c , gc , index ] = optimbase_function ( this , x , index )
45 // Not Authorized Calling sequences of the optimbase_function:
46 //   Rejected because there is no index in input :
47 //   [ this , f , index ] = optimbase_function ( this , x )
48 //   [ this , f ] = optimbase_function ( this , x )
49 //   Rejected because there is no index in output :
50 //   [ this , f ] = optimbase_function ( this , x , index )
51 //   [ this , f , g ] = optimbase_function ( this , x , index )
52 //   [ this , f , c ] = optimbase_function ( this , x , index )
53 //   [ this , f , g , c , gc ] = optimbase_function ( this , x , index )
54 //
55 // Calling sequences of the cost function:
56 //   > Without additionnal data
57 //   [ f , index ] = costf ( x , index )
58 //   [ f , g , index ] = costf ( x , index )
59 //   [ f , c , index ] = costf ( x , index )
60 //   [ f , g , c , gc , index ] = costf ( x , index )
61 //   > With additionnal data
62 //   [ f , index ] = costf ( x , index , a1, a2, ... )
63 //   [ f , g , index ] = costf ( x , index , a1, a2, ... )
64 //   [ f , c , index ] = costf ( x , index , a1, a2, ... )
65 //   [ f , g , c , gc , index ] = costf ( x , index , a1, a2, ... )
66 // Not Authorized Calling sequences of the cost function:
67 //   Rejected because there is no index in input :
68 //   [ f ] = costf ( this , x )
69 //   [ f , index ] = costf ( this , x )
70 //   [ f ] = costf ( this , x , a1, a2, ... )
71 //   [ f , index ] = costf ( this , x , a1, a2, ... )
72 //   Rejected because there is no index in output :
73 //   [ f ] = costf ( this , x , index )
74 //   [ f , g ] = costf ( this , x , index )
75 //   [ f , c ] = costf ( this , x , index )
76 //   [ f , g , c ] = costf ( this , x , index )
77 //   [ f ] = costf ( this , x , index , a1, a2, ... )
78 //   [ f , g ] = costf ( this , x , index , a1, a2, ... )
79 //   [ f , g , c ] = costf ( this , x , index , a1, a2, ... )
80 //   [ f , c ] = costf ( this , x , index , a1, a2, ... )
81 //
82 function varargout = optimbase_function ( this , x , index )
83     [lhs,rhs]=argn();
84     if ( rhs <> 3 ) then
85         errmsg = msprintf(gettext("%s: Unexpected number of input arguments : %d provided while 2 are expected."), "optimbase_function", rhs);
86         error(errmsg)
87     end
88     if ( ( lhs < 3 ) | ( lhs > 5 ) ) then
89         errmsg = msprintf(gettext("%s: Unexpected number of output arguments : %d provided while 3 to 5 are expected."), "optimbase_function", lhs);
90         error(errmsg)
91     end
92     if this.fun == "" then
93         errmsg = msprintf(gettext("%s: Empty function (use -function option)."), "optimbase_function")
94         error(errmsg)
95     end
96     this.funevals = this.funevals + 1;
97     if this.verbose == 1 then
98         msg = sprintf ( "Function Evaluation #%d, index=%d, x= [%s]" , ...
99         this.funevals , index, strcat(string(x)," "))
100         this = optimbase_log ( this , msg )
101     end
102     //
103     // Setup the callback and its arguments
104     //
105     funtype = typeof(this.fun)
106     if ( funtype == "function" ) then
107         __optimbase_f__ = this.fun
108         //
109         // Backward-compatibility: process the costfargument field
110         //
111         if ( typeof(this.costfargument) == "string" ) then
112             __optimbase_args__ = list()
113         else
114             __optimbase_args__ = list(this.costfargument)
115         end
116     else
117         __optimbase_f__ = this.fun(1)
118         __optimbase_args__ = list(this.fun(2:$))
119     end
120     if ( this.withderivatives ) then
121         if ( this.nbineqconst == 0 ) then
122             // [ f , g , index ] = costf ( x , index )
123             // [ f , g , index ] = costf ( x , index , a1, a2, ... )
124             // [ this , f , g , index ] = optimbase_function ( this , x , index )
125             [ f , g , index ] = __optimbase_f__ ( x , index , __optimbase_args__(1:$) );
126             if type(f) <> 1 | ~isreal(f) then
127                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 1);
128                 error(errmsg)
129             end
130             if type(g) <> 1 | ~isreal(g) then
131                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 2);
132                 error(errmsg)
133             end
134             if type(index) <> 1 | ~isreal(index) then
135                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 3);
136                 error(errmsg)
137             end
138             varargout(1) = this
139             varargout(2) = f
140             varargout(3) = g
141             varargout(4) = index
142         else
143             // [ f , g , c , gc , index ] = costf ( x , index )
144             // [ f , g , c , gc , index ] = costf ( x , index , a1, a2, ... )
145             // [ this , f , g , c , gc , index ] = optimbase_function ( this , x , index )
146             [ f , g , c , gc , index ] = __optimbase_f__ ( x , index , __optimbase_args__(1:$) );
147             if type(f) <> 1 | ~isreal(f) then
148                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 1);
149                 error(errmsg)
150             end
151             if type(g) <> 1 | ~isreal(g) then
152                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 2);
153                 error(errmsg)
154             end
155             if type(c) <> 1 | ~isreal(c) then
156                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 3);
157                 error(errmsg)
158             end
159             if type(gc) <> 1 | ~isreal(gc) then
160                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 4);
161                 error(errmsg)
162             end
163             if type(index) <> 1 | ~isreal(index) then
164                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 5);
165                 error(errmsg)
166             end
167             varargout(1) = this
168             varargout(2) = f
169             varargout(3) = g
170             varargout(4) = c
171             varargout(5) = gc
172             varargout(6) = index
173         end
174     else
175         if ( this.nbineqconst == 0 ) then
176             // [ f , index ] = costf ( x , index )
177             // [ f , index ] = costf ( x , index , a1, a2, ... )
178             // [ this , f , index ] = optimbase_function ( this , x , index )
179             [ f , index ] = __optimbase_f__ ( x , index , __optimbase_args__(1:$) );
180             if type(f) <> 1 | ~isreal(f) then
181                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 1);
182                 error(errmsg)
183             end
184             if type(index) <> 1 | ~isreal(index) then
185                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 2);
186                 error(errmsg)
187             end
188             varargout(1) = this
189             varargout(2) = f
190             varargout(3) = index
191         else
192             // [ f , c , index ] = costf ( x , index )
193             // [ f , c , index ] = costf ( x , index , a1, a2, ... )
194             // [ this , f , c , index ] = optimbase_function ( this , x , index )
195             [ f , c , index ] = __optimbase_f__ ( x , index , __optimbase_args__(1:$) );
196             if type(f) <> 1 | ~isreal(f) then
197                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 1);
198                 error(errmsg)
199             end
200             if type(c) <> 1 | ~isreal(c) then
201                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 2);
202                 error(errmsg)
203             end
204             if type(index) <> 1 | ~isreal(index) then
205                 errmsg = msprintf(_("%s: Wrong type for user function output argument #%d: A real matrix expected."), "optimbase_function", 3);
206                 error(errmsg)
207             end
208             varargout(1) = this
209             varargout(2) = f
210             varargout(3) = c
211             varargout(4) = index
212         end
213     end
214 endfunction
215