function ObjSamples = uevaluate(hFuncObj, nSamples, varargin)
% UEVALUATE evaluates user-defined uncertain object on a number of samples
%
% ObjSamples = uevaluate(hFuncObj, nSamples)
% ObjSamples = uevaluate(hFuncObj, nSamples, Vectorize)
% ObjSamples = uevaluate(hFuncObj, nSamples, OutType)
% ObjSamples = uevaluate(hFuncObj, nSamples, Vectorize, OutType)
%
% evaluate user-defined function hFuncObj,
% nSamples is the number of samples taken, special values are
% 0 - nominal object extracted (non-cell output allowed, and distribu
% tion should accept this value),
% 1 - a sample without cell wrapping allowed (see OutType).
% Vectorize is flag displaying that hFuncObj can accept arrays of samples
% 0 - if cannot,
% 1 - if it can,
% -1 - autodetection (default).
% OutType is string with return format definition,
% 'cell' - to return array of cells (default),
% 'val' - to return one sample without cell wrapping, valid only
% when nSamples is 0 or 1.
% $Id$
% ----1. parameter check ----------------------------------
switch nargin
case 2 % (hFuncObj, nSamples)
Vectorize = -1; % default autodetect value
OutType = 'cell'; % default cell packing
case 3 %(hFuncObj, nSamples, OutType) or (hFuncObj, nSamples, Vectorize)
if isa(varargin{1}, 'char') % (hFuncObj, nSamples, OutType)
Vectorize = -1;
OutType = varargin{1};
else % (hFuncObj, nSamples, Vectorize)
Vectorize = varargin{1};
OutType = 'cell';
end
case 4 % (hFuncObj, nSamples, Vectorize, OutType)
Vectorize = varargin{1};
OutType = varargin{2};
otherwise
error(['RACT:uevaluate:Input', 'Incorrect number of arguments.']);
end
% input error detection
if ~isa(hFuncObj, 'function_handle')
error(['RACT:uevaluate:InputType', 'First parameter must be function handle!']);
end
if ~isa(OutType, 'char')
error(['RACT:uevaluate:InputType', ['Unknown OutType value: ' num2str(OutType)]]);
end
switch OutType
case 'cell' % ok, user-function returns array of cells
case 'val' % only for nSamples = 0 or 1 - return the value of instance
if and(nSamples ~= 0, nSamples ~= 1)
error(['RACT:uevaluate:InputType', '''val'' argument valid only for nSamples = 0 or 1.']);
end
otherwise
error(['RACT:uevaluate:InputType', ['Unknown OutType value: ' OutType]]);
end
if ~(nSamples >= 0)
error(['RACT:uevaluate:InputType', ['Invalid number of iterations: ' num2str(nSamples)]]);
end
% ---#1. end of parameter check ------------------------------
% First call user-defined function once and
% extract uncertainties structure (in one-dimensional
% cell array). Empty values allowed.
% UVars = hFuncObj(1); - valid only in Matlab 7 (AT)
UVars = feval(hFuncObj, 1);
% number of uncertain variables
n = length(UVars);
% additional vector of types of uncertain variables used
% (0 for scalar, 1 for vector or 2 for matrix)
utype = zeros(n, 1);
for k = 1:n
if ~isempty(UVars{k}) % use only filled cells
if isa(UVars{k}, 'ubase') % UBASE variable admitted only
switch distrtype(UVars{k}) %UVars{k}.DistrType
case {'real_scalar_uniform', 'complex_scalar_uniform', 'real_scalar_gaussian'}
utype(k) = 0;
case {'real_vector_uniform', 'complex_vector_uniform', 'real_stable_discrete_poly_uniform', 'real_vector_gaussian'}
utype(k) = 1;
case {'real_matrix_uniform', 'complex_matrix_uniform', 'real_matrix_uniform_elem'}
utype(k) = 2;
otherwise
error(['RACT:uevaluate:Irrelevance', ['Unknown UBASE distribution: ' distrtype(UVars{k})]]);
end
else
error(['RACT:uevaluate:InputType', ['Unknown class met: ' class(UVars{k})]]);
end
else % undefined uncertainty, just skip
utype(k) = -1;
end
end
% TODO the idea?! return the instance of uncertain object (nominal or )
% then
%if strcmp(OutType, 'val') % nSamples == 0 or 1, see above parameter checking
% ObjSamples = hFuncObj(usample(UVars, nSamples)); -
% return;
%end
%% ?AT? here multitasking jobs can be paralleled
% generate samples as packed array
% (i.e. a scalar uncertain variable produces a vector, e.t.c.)
Samples = usample(UVars, nSamples);
if strcmp(OutType, 'val') % error check was before
ObjSamples = feval(hFuncObj, 0, Samples);
% unwrap cell if exist
if isa(ObjSamples, 'cell')
% UNCOMMENT WHEN USER-DEFINED DISTRIBUTIONS WILL BE ALLOWED (TODO - AT)
% if max(size(ObjSample)) == 1 % and it is not a user-defined array of cells
ObjSamples = ObjSamples{1};
% end
end
return;
end
%% ?AT? here multitasking jobs can be paralleled too
% try to call user-defined function hFuncObj
% which can return either cell array of uncertain objects corresponding
% to cell array of instancies of uncertainties, either just one
% instance of uncertain object
switch Vectorize
case 1
try % even if flag setted explicitly, consider Merphy Law
ObjSamples = feval(hFuncObj, 0, Samples);
catch
error(['RACT:uevaluate:Irrelevance', 'Seems like your function doesn''t allow vectorization indeed.']);
end
case 0 % one-by-one initialization
% initialization of array of samples,
% each of the cells refers to one uncertain variable
aSample = cell(size(UVars));
% preallocate cells for object instancies
ObjSamples = cell(nSamples, 1);
% a trick to recognize if output is cell-wrapped (old style), or not
% use first sample to do this check
m = 1;
for k = 1:n
switch utype(k)
case 0
aSample{k} = Samples{k}(m);
case 1
aSample{k} = Samples{k}(:, m);
case 2
aSample{k} = Samples{k}(:, :, m);
case -1
aSample{k} = [];
end
end
ObjSample = feval(hFuncObj, 0, aSample);
% check if it is old-style packing (obsolete? AT)
if isa(ObjSample, 'cell')
% UNCOMMENT WHEN USER-DEFINED DISTRIBUTIONS WILL BE ALLOWED (TODO - AT)
% if max(size(ObjSample)) == 1 % and it is not a user-defined array of cells
ObjSamples{m} = ObjSample{1};
onecellwrapped = 1;
% end
else % consider the user function return object sample as is
ObjSamples{m} = ObjSample;
onecellwrapped = 0;
end
% use two similar but different (speedup) cycles depending packing
if onecellwrapped == 0 % no packing
% MAIN cycle with the COMMENTS
for m = 2:nSamples
% extract a set of uncertain variables used from all of samples
%% ?AT? TODO ("gridding"), and cartesian product ??
for k = 1:n
switch utype(k)
case 0
aSample{k} = Samples{k}(m);
case 1
aSample{k} = Samples{k}(:, m);
case 2
aSample{k} = Samples{k}(:, :, m);
case -1
aSample{k} = [];
end
end
% call the user-defined function
%% ObjSample = hFuncObj(0, aSample); - valid only in Matlab 7 (AT)
ObjSample = feval(hFuncObj, 0, aSample);
% unwrap sampled object from cell array
ObjSamples{m} = ObjSample;
end
elseif onecellwrapped == 1 % one-cell packing
% see the comments above
for m = 2:nSamples
for k = 1:n
switch utype(k)
case 0
aSample{k} = Samples{k}(m);
case 1
aSample{k} = Samples{k}(:, m);
case 2
aSample{k} = Samples{k}(:, :, m);
case -1
aSample{k} = [];
end
end
ObjSample = feval(hFuncObj, 0, aSample);
ObjSamples{m} = ObjSample{1};
end
end
case -1 % autodetect
try % vectorized call first
% ObjSamples = hFuncObj(0, Samples); - valid only in Matlab 7 (AT)
ObjSamples = feval(hFuncObj, 0, Samples);
catch % if we are fail to, cast one-by-one evaluation
% see comments above, it is the same 'copy-paste' code
aSample = cell(size(UVars));
ObjSamples = cell(nSamples, 1);
for m = 1:nSamples
for k = 1:n
switch utype(k)
case 0
aSample{k} = Samples{k}(m);
case 1
aSample{k} = Samples{k}(:, m);
case 2
aSample{k} = Samples{k}(:, :, m);
case -1
aSample{k} = [];
end
end
ObjSample = feval(hFuncObj, 0, aSample);
ObjSamples{m} = ObjSample{1};
end
end
end
%% END OF THE FUNCTION