Updates to the OptimizerFactory and the MatlabInterface. Better access to EvAClient.
This commit is contained in:
@@ -1,41 +1,46 @@
|
||||
function int = JEInterface(interfaceName, fhandle, range, varargin)
|
||||
function int = JEInterface(fhandle, range, varargin)
|
||||
% EvA2 Interface for Matlab
|
||||
% JEInterface(interfaceName, fhandle, range [, optset, defaultargs])
|
||||
% JEInterface(interfaceName, fhandle, range)
|
||||
% JEInterface(interfaceName, fhandle, range, defaultargs)
|
||||
% JEInterface(interfaceName, fhandle, range, defaultargs, options...)
|
||||
|
||||
|
||||
% arguments:
|
||||
% interfaceName: a JEInterface instance needs to know its own
|
||||
% name as a String to allow callbacks from Java.
|
||||
% fhandle: a function handle defining the optimization target.
|
||||
% range: a 2 x dim array defining the solution subspace with lower and
|
||||
% upper bounds - or a scalar defining the bitwidth for binary problems.
|
||||
% optset: (optional) an optimset struct defining optimization parameters,
|
||||
% especially tolerance and maximum function calls. Defaults to the
|
||||
% EvA2 default values.
|
||||
% upper bounds - or a scalar defining the bitwidth for binary
|
||||
% problems.
|
||||
% defaultArgs: (optional) additional constant argument to the target
|
||||
% function, empty by default.
|
||||
% Recognized options are:
|
||||
% options: (optional) options as name-value pairs defining optimization parameters,
|
||||
% especially tolerance and maximum function calls.
|
||||
% Check makeOoptions for default settings.
|
||||
|
||||
% Further options may be specified using setOptions with a JE options struct.
|
||||
% Main options are:
|
||||
% TolX: convergence criterion in the solution space
|
||||
% TolFun: convergence criterion in the target space
|
||||
% MaxFunEvals: maximum number of function evaluations
|
||||
% Display: 'off'/'final'/'notify'/'iter', where 'notify' corresponds to
|
||||
% displaying every k-th iteration, which k=10 as default.
|
||||
% displaying every k-th iteration, with k=10 as default.
|
||||
% The termination criterion of a run is a combination of the TolX, TolFun and
|
||||
% MaxFunEvals criteria. The run terminates if MaxFunEvals has been reached
|
||||
% or the best solution changes both in domain and codomain less than TolX
|
||||
% and TolFun for a certain time, e.g. 100 evaluations.
|
||||
% and TolFun for a certain number of evaluations, which may be set using
|
||||
% TolXEvals and TolFunEvals, respectively.
|
||||
% To ignore a criterion, set it to 0. E.g. to perform 10^5 evaluations in
|
||||
% any case, set TolX=TolFun=0 and MaxFunEvals=10^5.
|
||||
%
|
||||
% You may define a 2xdim range with a double valued function handle or for
|
||||
% Define a 2 x dim range with a double valued function, or for
|
||||
% binary problems set a scalar as range defining the number of bits to be
|
||||
% used. The values passed to the function handle will then be arrays of
|
||||
% uint32, each of them representing 32 bits.
|
||||
|
||||
int.args = [];
|
||||
int.opts = optimset('MaxFunEvals', eva2.OptimizerFactory.getDefaultFitCalls, 'TolX', 1e-4, 'TolFun', 1e-4);
|
||||
int.opts = [];
|
||||
int.finished = 1;
|
||||
int.result = [];
|
||||
int.resultArr = [];
|
||||
int.callback='';
|
||||
int.f = '';
|
||||
int.dim = 0;
|
||||
int.range = [];
|
||||
@@ -47,50 +52,51 @@ int.optParams = [];
|
||||
int.optParamValues = [];
|
||||
int.hexMask=hex2dec('ffffffff');
|
||||
|
||||
if (isa(interfaceName, 'char'));
|
||||
int.callback = interfaceName;
|
||||
else
|
||||
error('Wrong first argument type, expected char');
|
||||
end
|
||||
if (isa(fhandle, 'function_handle'))
|
||||
int.f = fhandle;
|
||||
else
|
||||
error('Wrong second argument type, expected function_handle');
|
||||
end
|
||||
|
||||
disp('Setting up JEInterface...');
|
||||
if (isa(range, 'double') && (size(range,1) == 2))
|
||||
int.dim=size(range, 2);
|
||||
int.dim=size(range,2);
|
||||
int.range=transpose(range);
|
||||
s = sprintf('Double valued search space, dimension: %d', int.dim);
|
||||
disp(s);
|
||||
else
|
||||
%error('Wrong third argument type, expected double array of 2 x dim');
|
||||
if (size(range,1)==size(range,2)==1)
|
||||
if (length(range)==1)
|
||||
int.range=[];
|
||||
int.dim=range;
|
||||
s = sprintf('Binary valued search space, dimension: %d', int.dim);
|
||||
disp(s);
|
||||
else
|
||||
error('Wrong third argument type, expected double array of 2 x dim (double ranges) or scalar (binary bit width).');
|
||||
end
|
||||
end
|
||||
|
||||
int = class(int,'JEInterface');
|
||||
int.opts = makeOptions(int);
|
||||
|
||||
switch nargin
|
||||
case {3}
|
||||
case {4,5}
|
||||
if (isa(varargin{1}, 'struct'))
|
||||
int.opts = varargin{1};
|
||||
% DONT set default values if user leaves them blank
|
||||
% if (isempty(int.opts.TolX)) ; int.opts.TolX = 1e-4; end
|
||||
% if (isempty(int.opts.TolFun)) ; int.opts.TolFun = 1e-4; end
|
||||
else
|
||||
error('Wrong fifth argument type, expected optimset struct');
|
||||
if (nargin>2)
|
||||
int.args = varargin{1};
|
||||
disp('Fitness function argument: '); disp(int.args);
|
||||
if (nargin > 3)
|
||||
if (rem(nargin,2)==0)
|
||||
error('Invalid number of arguments!');
|
||||
end
|
||||
if (nargin > 4)
|
||||
int.args = varargin{2};
|
||||
disp('Reading options...');
|
||||
for i=2:2:nargin-2
|
||||
int=setOpt(int, varargin{i}, varargin{i+1});
|
||||
end
|
||||
otherwise
|
||||
error('Wrong number of arguments!')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% finally create the java object
|
||||
int.mp = eva2.server.go.problems.MatlabProblem(int.dim, int.range);
|
||||
disp('Java object created');
|
||||
|
||||
testEvalFunc(int);
|
||||
|
||||
|
||||
|
||||
|
@@ -5,4 +5,4 @@ function val = getOpt(int, optName)
|
||||
% optName: name of the option to change, e.g. 'MaxFunEvals'
|
||||
% optVal: new value
|
||||
|
||||
val = optimget(int.opts, optName);
|
||||
val = int.opts.(optName);
|
65
resources/MatlabInterface/@JEInterface/makeOptions.m
Normal file
65
resources/MatlabInterface/@JEInterface/makeOptions.m
Normal file
@@ -0,0 +1,65 @@
|
||||
function opts = makeOptions(int, varargin)
|
||||
% Create a JEInterface options set from scratch. Possible fields are:
|
||||
%'Display';
|
||||
%'MaxFunEvals';'MaxIter';'TolFun';'TolFunEvals';TolX';'TolXEvals', where
|
||||
% all but 'TolFunEvals', 'TolXEvals' are used similar to the optimset.
|
||||
% The latter two are interpreted as the numbers of evaluations required
|
||||
% to assume convergence. Default values are TolXEvals=TolFunEvals=200,
|
||||
% TolX=TolFun=1e-4, MaxFunEvals uses a default from EvA2.
|
||||
% Notice that this method creates a parameter set but does not assign it
|
||||
% to the interface instance. Use setOptions to do that.
|
||||
|
||||
allfields = {'Display'; 'MaxFunEvals';'MaxIter';'TolFun';'TolFunEvals';...
|
||||
'TolX';'TolXEvals'};
|
||||
|
||||
specialfields={'TolFunEvals', 'TolXEvals'};
|
||||
|
||||
nvararg=nargin-1;
|
||||
if rem(nvararg,2)==1
|
||||
error('Pass options in name-value pairs!');
|
||||
end
|
||||
|
||||
% create cell array
|
||||
structinput = cell(2,length(allfields));
|
||||
% fields go in first row
|
||||
structinput(1,:) = allfields';
|
||||
% []'s go in second row
|
||||
structinput(2,:) = {[]};
|
||||
% turn it into correctly ordered comma separated list and call struct
|
||||
opts = struct(structinput{:});
|
||||
|
||||
stdSet=optimset();
|
||||
|
||||
% standard options:
|
||||
opts.('MaxFunEvals') = eva2.OptimizerFactory.getDefaultFitCalls;
|
||||
opts.('TolX') = 1e-4;
|
||||
opts.('TolXEvals') = 200;
|
||||
opts.('TolFun') = 1e-4;
|
||||
opts.('TolFunEvals') = 200;
|
||||
|
||||
for i=1:nvararg/2
|
||||
name=varargin{2*i-1};
|
||||
value=varargin{(2*i)};
|
||||
% parse arguments
|
||||
if ~ischar(name)
|
||||
error('Expected char parameter name at index %d!', 2*i+1);
|
||||
else
|
||||
optIndex=strmatch(name,allfields, 'exact');
|
||||
if isempty(optIndex)
|
||||
error('Unknown option %s !', name);
|
||||
else
|
||||
if ~isempty(strmatch(name, specialfields,'exact'))
|
||||
% test for integer
|
||||
if (~isscalar(value) || ~isnumeric(value) || round(value)<1)
|
||||
error('invalid value type for %s, expecting numeric scalar > 1!', name);
|
||||
end
|
||||
value=round(value);
|
||||
else
|
||||
% test using optimset
|
||||
optimset(stdSet, name, value);
|
||||
end
|
||||
% assign to struct
|
||||
opts.(allfields{optIndex,:}) = value;
|
||||
end
|
||||
end
|
||||
end
|
@@ -43,15 +43,14 @@ if ((nargin == 2) || (nargin == 3))
|
||||
if (isempty(int.opts.TolX)) ; xTol = 1e-4; end
|
||||
if (isempty(int.opts.TolFun)) ; fTol = 1e-4; end
|
||||
|
||||
evalsForConv=100;
|
||||
% construct Terminators
|
||||
if ((xTol > 0) && (fTol > 0))
|
||||
% both criteria are given, use combination
|
||||
convTerm = CombinedTerminator(FitnessConvergenceTerminator(fTol, evalsForConv, 1, 1), PhenotypeConvergenceTerminator(xTol, evalsForConv, 1, 1), 1);
|
||||
convTerm = CombinedTerminator(FitnessConvergenceTerminator(fTol, int.opts.TolFunEvals, 1, 1), PhenotypeConvergenceTerminator(xTol, int.opts.TolXEvals, 1, 1), 1);
|
||||
else if (xTol > 0) % only phenotye convergence
|
||||
convTerm = PhenotypeConvergenceTerminator(xTol, evalsForConv, 1, 1);
|
||||
convTerm = PhenotypeConvergenceTerminator(xTol, int.opts.TolXEvals, 1, 1);
|
||||
else if (fTol > 0 ) % only fitness covnergence
|
||||
convTerm = FitnessConvergenceTerminator(fTol, evalsForConv, 1, 1);
|
||||
convTerm = FitnessConvergenceTerminator(fTol, int.opts.TolFunEvals, 1, 1);
|
||||
else
|
||||
convTerm = 'undef'; % signal that there is no terminator yet
|
||||
end
|
||||
|
@@ -1,9 +1,13 @@
|
||||
function int = setOpt(int, optName, optVal)
|
||||
% Set a single optimset value within the JI instance.
|
||||
% Set a single option value within the JI instance.
|
||||
% Arguments:
|
||||
% int: the JEInterface instance
|
||||
% optName: name of the option to change, e.g. 'MaxFunEvals'
|
||||
% optVal: new value
|
||||
|
||||
opts = optimset(int.opts, optName, optVal);
|
||||
% this only makes sure the option actally exists and is valid
|
||||
makeOptions(int, optName, optVal);
|
||||
|
||||
opts = int.opts;
|
||||
opts.(optName) = optVal;
|
||||
int.opts = opts;
|
@@ -1,7 +1,25 @@
|
||||
function int = setOptions(int, options)
|
||||
% Set the optimization options for the interface.
|
||||
function int = setOptions(int, usrOpts)
|
||||
% Set the optimization options for the interface. The existing options are
|
||||
% overwritten by the given setings.
|
||||
% parameters:
|
||||
% int: an interface instance
|
||||
% options: an optimset instance
|
||||
% usrOpts: a JE options structure
|
||||
|
||||
fn=fieldnames(usrOpts);
|
||||
|
||||
options = int.opts;
|
||||
|
||||
try
|
||||
for i=1:length(fn)
|
||||
% make sure all option fields and values are valid
|
||||
% fn(i)
|
||||
% ischar(fn(i))
|
||||
makeOptions(int, char(fn(i)), usrOpts.(char(fn(i))));
|
||||
options.(char(fn(i))) = usrOpts.(char(fn(i)));
|
||||
end
|
||||
catch ME
|
||||
error('invalid option "%s"... check makeOptions to learn about available options', char(fn(i)));
|
||||
|
||||
end
|
||||
|
||||
int.opts = options;
|
24
resources/MatlabInterface/@JEInterface/setVerbose.m
Normal file
24
resources/MatlabInterface/@JEInterface/setVerbose.m
Normal file
@@ -0,0 +1,24 @@
|
||||
function int=setVerbose(int, bOn, varargin)
|
||||
% Activate debug output for the MatlabProblem.
|
||||
% setVerbose(JI, bOn [, dbgfile])
|
||||
% It is written to a file with given name or to matlabproblem-debug.log
|
||||
% if none is given.
|
||||
% JI: the interface instance
|
||||
% bOn: 1 activates debug output, 0 deactivates it
|
||||
% dbgfile: optional filename
|
||||
%
|
||||
|
||||
if (nargin > 2)
|
||||
if ischar(varargin{1})
|
||||
fname=varargin{1};
|
||||
disp('Writing debug output to ');
|
||||
disp(fname);
|
||||
else
|
||||
disp('Invalid third argument, expected char. Using default output file name');
|
||||
end
|
||||
else
|
||||
fname=null;
|
||||
end
|
||||
|
||||
int.mp.setDebugOut( bOn==1, fname);
|
||||
|
56
resources/MatlabInterface/@JEInterface/testEvalFunc.m
Normal file
56
resources/MatlabInterface/@JEInterface/testEvalFunc.m
Normal file
@@ -0,0 +1,56 @@
|
||||
function testEvalFunc(int)
|
||||
% Test the fitness function output format.
|
||||
wordwidth=32;
|
||||
|
||||
if (isempty(int.range)==1)
|
||||
% binary problem
|
||||
s=sprintf('Binary problem of bitwidth %d', int.dim);
|
||||
disp(s);
|
||||
numInts=ceil(int.dim/wordwidth);
|
||||
% generate trial vector
|
||||
x=ceil(rand(1,numInts).*(2^wordwidth));
|
||||
overheadBits=numInts*wordwidth-int.dim;
|
||||
x(numInts)=bitshift(x(numInts),-overheadBits); % shift right by overhead
|
||||
else
|
||||
% double problem
|
||||
x=rand(1, int.dim);
|
||||
s=sprintf('Real valued problem in %d dimensions and range %s ', int.dim, mat2str(int.range));
|
||||
disp(s);
|
||||
for i=1:int.dim
|
||||
x(i)=int.range(i,1)+x(i)*(int.range(i,2)-int.range(i,1));
|
||||
end
|
||||
end
|
||||
|
||||
disp('Testing value: ')
|
||||
disp(x);
|
||||
|
||||
try
|
||||
if (isempty(int.args))
|
||||
res = feval(int.f, x);
|
||||
else
|
||||
res = feval(int.f, x, int.args);
|
||||
end
|
||||
catch ME
|
||||
disp('Function evaluation failed:');
|
||||
disp(ME.message);
|
||||
error('Test failed!');
|
||||
end
|
||||
|
||||
disp('Function returned: ');
|
||||
disp(res);
|
||||
|
||||
if (min(size(res)) > 1)
|
||||
disp('Warning: unable to optimize matrix representations - use 1 times m output only');
|
||||
else
|
||||
if (size(res,1)>1)
|
||||
disp('Warning: use dimensions 1 times m instead of m times 1');
|
||||
else
|
||||
if ~(sum(isnumeric(res))==size(res,1)*size(res,2))
|
||||
disp('Warning: result seems to contain non-numeric elements!');
|
||||
else
|
||||
disp('Ok.');
|
||||
end
|
||||
end;
|
||||
end
|
||||
|
||||
|
Reference in New Issue
Block a user