diff --git a/resources/MatlabInterface/@JEInterface/JEInterface.m b/resources/MatlabInterface/@JEInterface/JEInterface.m index bea761dc..bd973e3c 100644 --- a/resources/MatlabInterface/@JEInterface/JEInterface.m +++ b/resources/MatlabInterface/@JEInterface/JEInterface.m @@ -17,6 +17,7 @@ int.args = []; int.opts = optimset('MaxFunEvals', javaeva.OptimizerFactory.getDefaultFitCalls, 'TolX', 1e-4, 'TolFun', 1e-4); int.finished = 1; int.result = []; +int.resultArr = []; int.callback=''; int.f = ''; int.dim = 0; @@ -24,6 +25,9 @@ int.range = []; int.mp = []; int.msg = ''; int.funCalls = 0; +int.mediator = ''; +int.optParams = []; +int.optParamValues = []; if (isa(interfaceName, 'char')); int.callback = interfaceName; @@ -35,6 +39,7 @@ if (isa(fhandle, 'function_handle')) else error('Wrong second argument type, expected function_handle'); end + if (isa(range, 'double') && (size(range,1) == 2)) int.dim=length(range); int.range=transpose(range); @@ -49,8 +54,9 @@ switch nargin case {4,5} if (isa(varargin{1}, 'struct')) int.opts = varargin{1}; - if (isempty(int.opts.TolX)) ; int.opts.TolX = 1e-4; end - if (isempty(int.opts.TolFun)) ; int.opts.TolFun = 1e-4; end + % 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'); end diff --git a/resources/MatlabInterface/@JEInterface/getDesc.m b/resources/MatlabInterface/@JEInterface/getDesc.m new file mode 100644 index 00000000..4cff8225 --- /dev/null +++ b/resources/MatlabInterface/@JEInterface/getDesc.m @@ -0,0 +1,11 @@ +function desc = getDesc(int, ID) +% Return the String description of an indicated optimizer +% with member descriptions. + +import javaeva.gui.BeanInspector; +import javaeva.server.modules.GOParameters; +import javaeva.OptimizerFactory; + +params = OptimizerFactory.getParams(ID, int.mp); +desc = BeanInspector.getDescription(params.getOptimizer, false); + diff --git a/resources/MatlabInterface/@JEInterface/getMultipleResults.m b/resources/MatlabInterface/@JEInterface/getMultipleResults.m new file mode 100644 index 00000000..444ead28 --- /dev/null +++ b/resources/MatlabInterface/@JEInterface/getMultipleResults.m @@ -0,0 +1,21 @@ +function [sols, fits] = getMultipleResults(int) +% Returns a set of optimization solutions if the run has been finished, or +% a singel intermediate solution if the run has not finished yet or an +% empty array if there is no intermediate solution yet. + +if (isFinished(int)) + sols = int.resultArr; +else + sols = int.mp.getIntermediateResult(); +end + +fits=zeros(size(sols,1),1); + +for i=1:size(sols,1) + %disp(sols(i,:)); + if (isempty(int.args)) + fits(i) = feval(int.f, sols(i,:)); + else + fits(i) = feval(int.f, sols(i,:), int.args); + end +end \ No newline at end of file diff --git a/resources/MatlabInterface/@JEInterface/getProgress.m b/resources/MatlabInterface/@JEInterface/getProgress.m new file mode 100644 index 00000000..13bfcf88 --- /dev/null +++ b/resources/MatlabInterface/@JEInterface/getProgress.m @@ -0,0 +1,5 @@ +function b = getProgress(int) +% Returns the number of function calls performed during optimization (not +% post processing) + +b = int.mp.getProgress; diff --git a/resources/MatlabInterface/@JEInterface/getResult.m b/resources/MatlabInterface/@JEInterface/getResult.m index 390a96db..1921d419 100644 --- a/resources/MatlabInterface/@JEInterface/getResult.m +++ b/resources/MatlabInterface/@JEInterface/getResult.m @@ -1,10 +1,23 @@ -function v = getResult(int) -% Returns the optimization solution if the run has been finished, or an -% intermediate solution if the run has not finished yet or an empty array +function [sol, fit] = getResult(int) +% Returns the optimization solution and its fitness if the run has been finished, or an +% intermediate solution and ints fitness if the run has not finished yet or an empty array % if there is no intermediate solution yet. +% [sol, fit] = getResult(int) if (isFinished(int)) - v = int.result; + sol = int.result; else - v = int.mp.getIntermediateResult(); -end \ No newline at end of file + sol = int.mp.getIntermediateResult(); +end + +if (isempty(sol)) + fit = NaN; +else + if (isempty(int.args)) + fit = feval(int.f, sol); + else + fit = feval(int.f, sol, int.args); + end +end +%disp('Fitness: '); +%disp(y); \ No newline at end of file diff --git a/resources/MatlabInterface/@JEInterface/optimize.m b/resources/MatlabInterface/@JEInterface/optimize.m index a261546a..effae025 100644 --- a/resources/MatlabInterface/@JEInterface/optimize.m +++ b/resources/MatlabInterface/@JEInterface/optimize.m @@ -1,18 +1,18 @@ function retInt = optimize(int, optType, varargin) % Start a JavaEvA optimization run. % optimize(interface, optType, [, outputFilePrefix ] ) -% where +% where % interface: instance of JEInterface % optType: integer indicating the type of the optimization strategy % to use. % resultFilePrefix: (optional) char prefix for an optional verbose % output file -if (int.finished == 0) +if (int.finished == 0) error('please wait for the current run to finish'); end if ((nargin == 2) || (nargin == 3)) - if (nargin == 3) + if (nargin == 3) outputFilePrefix = varargin{1}; else outputFilePrefix = 'none'; @@ -27,27 +27,60 @@ if ((nargin == 2) || (nargin == 3)) xTol = int.opts.TolX; maxEvals = int.opts.MaxFunEvals; fTol = int.opts.TolFun; - % construct Terminators + import javaeva.server.go.operators.terminators.PhenotypeConvergenceTerminator; - import javaeva.server.go.operators.terminators.FitnessConvergenceTerminator; + import javaeva.server.go.operators.terminators.FitnessConvergenceTerminator; import javaeva.server.go.operators.terminators.CombinedTerminator; import javaeva.server.go.operators.terminators.EvaluationTerminator; + import javaeva.OptimizerFactory; % set some default values if theyre not given - if (isempty(int.opts.TolX)) ; xTol = 1e-4; end - if (isempty(int.opts.TolFun)) ; fTol = 1e-4; end % fminsearch, for example, always uses TolX and TolFun with default % values of 1e-4 in . Thats what we do as well - convTerm = CombinedTerminator(FitnessConvergenceTerminator(fTol, int32(5), 0, 1), PhenotypeConvergenceTerminator(xTol, 5, 0, 1), 1); - - % if MaxFunEvals is defined additionally, combine an - % EvaluationTerminator in disjunction, as Matlab does. - if (~isempty(maxEvals)) - javaeva.OptimizerFactory.setTerminator(convTerm); - javaeva.OptimizerFactory.addTerminator(EvaluationTerminator(maxEvals), 0); + if (isempty(int.opts.TolX)) ; xTol = 1e-4; end + if (isempty(int.opts.TolFun)) ; fTol = 1e-4; end + % construct Terminators + if ((xTol > 0) && (fTol > 0)) + % both criteria are given, use combination + convTerm = CombinedTerminator(FitnessConvergenceTerminator(fTol, 100, 1, 1), PhenotypeConvergenceTerminator(xTol, 100, 1, 1), 1); + else if (xTol > 0) % only phenotye convergence + convTerm = PhenotypeConvergenceTerminator(xTol, 100, 1, 1); + else if (fTol > 0 ) % only fitness covnergence + convTerm = FitnessConvergenceTerminator(fTol, 100, 1, 1); + else + convTerm = 'undef'; % signal that there is no terminator yet + end + end end - - int.mp.optimize(optType, outputFilePrefix); + + if (ischar(convTerm)) % if no convergence terminator is defined so far, use fitness calls + if (isempty(maxEvals)) + error('Error: no termination criterion defined! Please check options.'); + % int.opts.MaxFunEvals = OptimizerFactory.getDefaultFitCalls; + % maxEvals = OptimizerFactory.getDefaultFitCalls; + end + convTerm = EvaluationTerminator(maxEvals); + javaeva.OptimizerFactory.setTerminator(convTerm); + else % there is a convergence terminator + javaeva.OptimizerFactory.setTerminator(convTerm); % so set it + if (~isempty(maxEvals)) + % if TolX/TolFun plus MaxFunEvals is defined additionally, combine an + % EvaluationTerminator in disjunction, as Matlab does. + javaeva.OptimizerFactory.addTerminator(EvaluationTerminator(maxEvals), 0); + end + end + + % set display + if (strcmp(int.opts.Display,'off') || isempty(int.opts.Display)) + int.mp.setStatsOutput(0); + elseif (strcmp(int.opts.Display, 'iter')) + int.mp.setStatsOutput(1); + else + error('invalid Display option, only off/iter are recognized'); + end + + int=runEvalLoopJE(int, 1, optType, outputFilePrefix, -1, -1, -1); + else error('Wrong number of arguments!') end diff --git a/resources/MatlabInterface/@JEInterface/optimizeWith.m b/resources/MatlabInterface/@JEInterface/optimizeWith.m new file mode 100644 index 00000000..80b015f2 --- /dev/null +++ b/resources/MatlabInterface/@JEInterface/optimizeWith.m @@ -0,0 +1,57 @@ +function retInt = optimizeWith(int, optType, varargin) +% Start a JavaEvA optimization run with specific optimizer parameter settings. +% optimize(interface, optType, [, outputFilePrefix ] [, memName, memVal]* ) +% where +% interface: instance of JEInterface +% optType: integer indicating the type of the optimization strategy +% to use. +% resultFilePrefix: (optional) char prefix for an optional verbose +% output file +% memName: character name of a member of the optimizer +% memVal: value to set for the member. +% Note that the parameter settings will not be stored and remain valid only for +% the current optimization run. + + +% This just reads the parameters, sets them as interface members and then +% calls the standard optimize method. + +if (int.finished == 0) + error('please wait for the current run to finish'); +end +if (nargin < 2) + error('invalid number of arguments!'); +end + +if (nargin == 2) + % standard case, just call optimize + retInt = optimize(int, optType); +elseif (nargin == 3) + % standard case, just call optimize + retInt = optimize(int, optType, varargin{1}); +else + if (mod(nargin, 2) == 1) % odd arguments! There is an outputfilePrefix! + nextMem = 2; + output = varargin{1}; + else + nextMem = 1; + output = ''; + end + pairCnt = (nargin-nextMem-1)/2; + parValues(1) = {-1}; +% parArr = ones(2*pairCnt,1); % parameter array + for i=1:pairCnt + % load parameter/value pairs into an array + parNames(i) = cellstr(varargin{nextMem}); + parValues(i) = {varargin{nextMem+1}}; +% if (~ischar(parArr(i))) +% error('invalid argument, member names must be char'); +% end + nextMem = nextMem+2; + end + int.optParams = parNames; + int.optParamValues = parValues; + retInt = optimize(int, optType, output); + int.optParams = []; + int.optParamValues = []; +end \ No newline at end of file diff --git a/resources/MatlabInterface/@JEInterface/postProcess.m b/resources/MatlabInterface/@JEInterface/postProcess.m new file mode 100644 index 00000000..e83d481e --- /dev/null +++ b/resources/MatlabInterface/@JEInterface/postProcess.m @@ -0,0 +1,35 @@ +function int = postProcess(int, steps, sigmaClust, varargin) +% Do post processing of the last optimization results and export +% the solution set to the JEInterface. +% int=postProcess(int, steps, sigmaClust [, nBest]) +% Either of the parameters steps and sigmaClust may be 0 to leave out +% hill-climbing or clustering step. Setting both to 0 is not meaningful. +% The optional nBest parameter gives an upper bound to the number of +% returned solutions, which are sorted by fitness. Leaving this parameter +% out means that all solutions suggested by the optimizer (after +% clustering if activated) are returned, the number of which is usually, +% but not for all optimizers (e.g., not for CBN), limited to the population size. +% +% Arguments: +% int: the JEInterface instance +% steps: number of hill climbing steps to perform or 0 +% sigmaClust: paramter for the density based clustering to perform or 0, +% relative to the problem range +% nBest: (optional) maximum number of solutions to return + + +% stepSize: (optional) step size of the stochastic hill climber. + +if (int.finished == 0) + error('please wait for the current run to finish'); +end + +int.finished = 0; + +if (nargin > 3) && (isnumeric(varargin{1})) + nBest = varargin{1}; +else + nBest = -1; +end + +int=runEvalLoopJE(int, 2, -1, '', steps, sigmaClust, nBest); diff --git a/resources/MatlabInterface/@JEInterface/runEvalLoopJE.m b/resources/MatlabInterface/@JEInterface/runEvalLoopJE.m new file mode 100644 index 00000000..ca4ae9c3 --- /dev/null +++ b/resources/MatlabInterface/@JEInterface/runEvalLoopJE.m @@ -0,0 +1,86 @@ +function int=runEvalLoopJE(int, optOrPostProc, optType, outputFilePrefix, steps, sigmaClust, nBest) +% Internal method starting a JavaEvA optimization loop. +% Calling this directly may interfere with optimization. + +% optOrPostProc: 1 for optimize, 2 for postProcess +% optType, outputFilePrefix are parameters for optimize, dont care when +% postprocessing. +% steps, sigmaClust and nBest are parameters for postProcess, dont care +% when optimizing. nBest may be -1 to show all. + +global stopOptimization + +if ~isempty(int.mediator) + int.mediator.quit + int.mediator=''; +end + +% set up a mediator and inform JE +int.mediator = javaeva.server.go.problems.MatlabEvalMediator; +int.mp.setMediator(int.mediator); + +% start the JE thread +if (optOrPostProc == 1) + stopText='Stop JavaEvA optimization'; + int.mp.optimize(optType, outputFilePrefix, int.optParams, int.optParamValues); +else % post processing + stopText='Stop JavaEvA post processing'; + int.mp.requestPostProcessing(steps, sigmaClust, nBest); +end + +% handle the case when the optimization has been called from a users script +% and not from the toolboxes parameter estimation function (which has an +% own stop button). we decide this by checking if the global variable +% stopOptimization is empty. if it is then it is not the toolbox calling +% and we create an own button to stop it. +if isempty(stopOptimization), + % create a cancel button box (only in the case that + h=figure('Position',[100 600 250 80], 'MenuBar', 'none', 'Name', 'JavaEvA optimization running...', 'NumberTitle','off'); + uicontrol(h,'Style', 'pushbutton', 'String', 'Cancel', 'Position', [25 25 60 30], 'Callback', 'global stopOptimization; stopOptimization=1;'); + uicontrol(h,'Style', 'text', 'String', stopText, 'Position', [100 25 120 30]); + drawnow; + % set it to 0 now + stopOptimization = 0; + % set flag for non toolbox optimization + nontoolboxopt = 1; +else + % its an estimation using the toolbox' parameter estimation thing + nontoolboxopt = 0; +end + +stopOnce=1; + +% repeat the mediator thread and eval call until finished +while (~int.mediator.isFinished()) + int.mediator.run; + if (~int.mediator.isFinished()) + x = int.mediator.getQuestion(); + if (isempty(int.args)) + res = feval(int.f, x); + else + res = feval(int.f, x, int.args); + end + int.mediator.setAnswer(res); + drawnow; + if ((stopOptimization==1) && (stopOnce==1)) + disp('User interrupt requested ...'); + stopOptimize(int); + stopOnce=0; + end + end +end + +% write back results +int=setResultJE(int, int.mediator.getSolution()); +int=setResultArrayJE(int, int.mediator.getSolutionSet()); + +int.mediator.quit; % just in case +int.mediator=''; + +% handle the case when the optimization has been called from a users script +% and not from the toolboxes parameter estimation function (which has an +% own stop button). we decide this by checking nontoolboxopt +if nontoolboxopt == 1, + close(h); + clear global stopOptimization +end \ No newline at end of file diff --git a/resources/MatlabInterface/@JEInterface/setResultArrayJE.m b/resources/MatlabInterface/@JEInterface/setResultArrayJE.m new file mode 100644 index 00000000..ab4e2d4a --- /dev/null +++ b/resources/MatlabInterface/@JEInterface/setResultArrayJE.m @@ -0,0 +1,9 @@ +function int = setResultArrayJE(int, arrData) +% Interface function to be called by JavaEvA 2. + +% Write back a whole solution set + +int.finished = 1; +int.msg=int.mp.getInfoString; +int.funCalls=int.mp.getFunctionCalls; +int.resultArr = arrData; \ No newline at end of file diff --git a/resources/MatlabInterface/@JEInterface/showOptimizers.m b/resources/MatlabInterface/@JEInterface/showOptimizers.m new file mode 100644 index 00000000..5c03fb36 --- /dev/null +++ b/resources/MatlabInterface/@JEInterface/showOptimizers.m @@ -0,0 +1,5 @@ +function showOptimizers(int) +% Show a list of JavaEvA optimizers accessible through the JEInterface +% and their access ID numbers. + +javaeva.OptimizerFactory.showOptimizers diff --git a/resources/MatlabInterface/@JEInterface/stopOptimize.m b/resources/MatlabInterface/@JEInterface/stopOptimize.m index a7d6c540..b6cdcb87 100644 --- a/resources/MatlabInterface/@JEInterface/stopOptimize.m +++ b/resources/MatlabInterface/@JEInterface/stopOptimize.m @@ -1,4 +1,9 @@ function int = stopOptimize(int) % Stop a running optimization -int.mp.stopOptimize +%disp('in Stop!'); +int.mp.stopOptimize; +%if (~isempty(int.mediator)) +% int.mediator.quit; % just in case +% int.mediator=''; +%end \ No newline at end of file