gusucode.com > 十大算法matlab程序说明 > 十大算法matlab程序说明/遗传退火法/validate.m
function [gl,ff,o] = validate(gLength,fitness,o) %VALIDATE validates the contents of the fitness function, genome length and options struct. % [gLength,fitness, OUT] = VALIDATE(GenomeLength,FitnessFcn,IN) validates the FitnessFcn, GenomeLength and % the structure IN. OUT is a structure which have all the fields in IN and it gets other % fields like FitnessFcn, GenomeLength, etc. % % This function is private to GA. % Copyright 2003-2005 The MathWorks, Inc. % $Revision: 1.26.6.5.2.1 $ $Date: 2005/07/17 06:06:36 $ msg = nargchk(3,3,nargin); if ~isempty(msg) error('MATLAB:Validate:numInputs', ... 'VALIDATE requires one structure of the format created by GAOPTIMSET.'); end %We need to validate ALL the information, bundle them all o.FitnessFcn = fitness; o.GenomeLength = gLength; %gaoptimset does not return 2 fields, which need to be validated options = gaoptimset; options.FitnessFcn = []; options.GenomeLength = []; %Does the options structure contain the right fields? template = fieldnames(options); oFields = fieldnames(o); f = find(0 == ismember(template,oFields)); if(~isempty(f)) msg = sprintf('The field "%s" is missing from the gaoptimset Structure.\n',template{f}); error('gads:VALIDATE:missingField',msg); end f = find(0 == ismember(oFields,template)); if(~isempty(f)) msg = sprintf('There is an unexpected field "%s" in the gaoptimset Structure.\n',oFields{f}); warning('gads:VALIDATE:unexpectedField',msg); end % range check each field validNumberofVariables(o.GenomeLength); stringSet('PopulationType',o.PopulationType,{'doubleVector','custom','bitString'}); positiveIntegerArray('PopulationSize',o.PopulationSize); realUnitScalar('CrossoverFraction',o.CrossoverFraction); nonNegInteger('EliteCount',o.EliteCount); o = rangeCorrection(o,'PopInitRange'); populationCheck(o); positiveInteger('MigrationInterval',o.MigrationInterval); realUnitScalar('MigrationFraction',o.MigrationFraction); stringSet('MigrationDirection',o.MigrationDirection,{'both','forward'}); stringSet('Display',o.Display,{'off','none','iter','final','diagnose'}); stringSet('Vectorized',o.Vectorized,{'on','off'}); nonNegScalar('TolFun',o.TolFun); nonNegScalar('TolCon',o.TolCon); positiveInteger('Generations',o.Generations); positiveScalar('TimeLimit',o.TimeLimit); positiveInteger('StallGenLimit',o.StallGenLimit); positiveScalar('StallTimeLimit',o.StallTimeLimit); realScalar('FitnessLimit',o.FitnessLimit); positiveInteger('PlotInterval',o.PlotInterval); % These functions not only VALIDATE, they seperate ftns from args for % speed. o = functionHandleOrCell(o,'FitnessFcn',o.FitnessFcn); o = functionHandleOrCell(o,'FitnessScalingFcn',o.FitnessScalingFcn); o = functionHandleOrCell(o,'SelectionFcn',o.SelectionFcn); o = functionHandleOrCell(o,'CrossoverFcn',o.CrossoverFcn); o = functionHandleOrCell(o,'MutationFcn',o.MutationFcn); o = functionHandleOrCell(o,'CreationFcn',o.CreationFcn); if ~isempty(o.HybridFcn) o = functionHandleOrCell(o,'HybridFcn',o.HybridFcn); end % protect against Elite Count greater than population Size. if ( o.EliteCount >= sum(o.PopulationSize) ) msg = sprintf('Elite count must be less than Population Size.'); error('gads:VALIDATE:EliteCountGTPop',msg); end % this special case takes an array of function cells o = functionHandleOrCellArray(o,'PlotFcns',o.PlotFcns); o = functionHandleOrCellArray(o,'OutputFcns',o.OutputFcns); %Assign all the outputs; ff = o.FitnessFcn; gl = o.GenomeLength; %Remove these fields we added in options o=rmfield(o,{'FitnessFcn','GenomeLength'}); %------------------------------------------------------------------- % any positive integer function positiveInteger(property,value) valid = isreal(value) && isscalar(value) && (value > 0) && (value == floor(value)); if(~valid) msg = sprintf('The field ''%s'' must contain a positive integer.',property); error('gads:VALIDATE:PostiveInteger:notPosInteger',msg); end %------------------------------------------------------------------- % any nonnegative integer function nonNegInteger(property,value) valid = isreal(value) && isscalar(value) && (value >= 0) && (value == floor(value)); if(~valid) msg = sprintf('The field ''%s'' must contain a non negative integer.',property); error('gads:VALIDATE:NonNegInteger:negativeNum',msg); end %------------------------------------------------------------------- % any scalar >= 0 function nonNegScalar(property,value) valid = isreal(value) && isscalar(value) && (value >= 0); if(~valid) msg = sprintf('The field ''%s'' must contain a scalar.',property); error('gads:VALIDATE:greaterEqualZeroScalar:lessThanZeroScalar',msg); end %------------------------------------------------------------------- % any positive scalar function positiveScalar(property,value) valid = isreal(value) && isscalar(value) && (value > 0); if(~valid) msg = sprintf('The field ''%s'' must contain a positive scalar.',property); error('gads:VALIDATE:PositiveScalar:notPosScalar',msg); end %------------------------------------------------------------------- function positiveIntegerArray(property,value) allValid = true; for i = 1:length(value) valid = isreal(value(i)) && (value(i) == floor(value(i))); allValid = allValid && valid; end if(~valid) msg = sprintf('The field ''%s'' must contain a positive integer.',property); error('gads:VALIDATE:POSITIVEINTEGERARRAY:notPosIntegerArray',msg); end %------------------------------------------------------------------- % A scalar on the interval [0,1] function realUnitScalar(property,value) valid = isreal(value) && isscalar(value) && (value >= 0) && (value <= 1); if(~valid) msg = sprintf('The field ''%s'' must contain a scalar on the interval (0,1)',property); error('gads:VALIDATE:REALUNITSCALAR:notScalarOnUnitInterval',msg); end %------------------------------------------------------------------- % A scalar function realScalar(property,value) valid = isreal(value) && isscalar(value); if(~valid) msg = sprintf('The field ''%s'' must contain a scalar',property); error('gads:VALIDATE:REALSCALAR:notScalar',msg); end %------------------------------------------------------------------- % Number of variables function validNumberofVariables(GenomeLength) valid = isnumeric(GenomeLength) && isscalar(GenomeLength)&& (GenomeLength > 0) ... && (GenomeLength == floor(GenomeLength)); if(~valid) msg = sprintf('Number of variables (NVARS) must be a positive integer.'); error('gads:VALIDATE:validNumberofVariables:notValidNvars',msg); end %------------------------------------------------------------------------- % if it's a scalar fcn handle or a cellarray starting with a fcn handle and % followed by something other than a fcn handle, return parts, else empty function [handle,args] = isFcn(x) handle = []; args = {}; %If x is a cell array with additional arguments, handle them if iscell(x) && ~isempty(x) args = x(2:end); handle = x{1}; else args = {}; handle = x; end %Only function_handle or inlines are allowed if ~(isa(handle,'inline') || isa(handle,'function_handle')) handle = []; end %------------------------------------------------------------------- % a function Handle or a cell array starting with a function handle. function options = functionHandleOrCell(options,property,value) [handle,args] = isFcn(value); if(~isempty(handle)) && (isa(handle,'inline') || isa(handle,'function_handle')) options.(property) = handle; options.([property 'Args']) = args; return end if strcmp(property,'FitnessFcn') msg = sprintf('The fitness function must be a function handle.'); else msg = sprintf('The field ''%s'' must contain a function handle.',property); end error('gads:VALIDATE:FUNCTIONHANDLEORCELL:needHandleOrInline',msg); %--------------------------------------------------------------------- % the most complex one. A fcn handle, a handle plus args, or an array of % same. function options = functionHandleOrCellArray(options,property,value) % clear out any old value options.(property) = {}; options.([property 'Args']) = {}; %if a scalar ~cell is passed convert to cell (for clarity, not speed) if ~iscell(value) && isscalar(value) value = {value}; end % If value is an array of functions, it must be a cell array for i = 1:length(value) candidate = value(i); %If any element is also a cell array if iscell(candidate) if isempty(candidate{1}) continue; end %Sometimes the variable 'candidate' might have nested cell array %e.g. {{@outputfcn, p1,p2}} instead of just %{@outputfcn,p1,p2}. The following code gets rid of extra braces, %which are typically introduced by GUI import/export options. temp = candidate{1}; while iscell(temp) && isscalar(temp) candidate = temp(1); temp = candidate{1}; end [handle,args] = isFcn(candidate{:}); else [handle,args] = isFcn(candidate); end if(~isempty(handle)) && isa(handle,'function_handle') options.(property){i} = handle; options.([property 'Args']){i} = args; else msg = sprintf('The field ''%s'' must contain a function handle.',property); error('gads:VALIDATE:FUNCTIONHANDLEORCELLARRAY:needHandleOrInline',msg); end end %---------------------------------------------------------------- % one of a set of strings function stringSet(property,value,set) for i = 1:length(set) if(strcmpi(value,set{i})) return; end end msg = sprintf('The field %s must contain one of these strings: %s %s %s %s %s',property,set{:}); error('gads:VALIDATE:STRINGSET:notCorrectChoice',msg); %---------------------------------------------------------------- function options = rangeCorrection(options,property) %Check the size of PopInitRange Range = options.PopInitRange; %check only for double data type range if ~isa(Range,'double') return; end if size(Range,1) ~=2 msg = sprintf('The field ''%s'' must have two rows.',property); error('gads:VALIDATE:RANGECORRECTION:invalidPopInitRange',msg); end lb = Range(1,:); lb = lb(:); lenlb = length(lb); ub = Range(2,:); ub = ub(:); lenub = length(ub); nvars = options.GenomeLength; %This field was inserted % Check maximum length if lenlb > nvars warning('gads:VALIDATE:extraRange','Length of lower range is > number of variables; ignoring extra bounds.'); lb = lb(1:nvars); lenlb = nvars; elseif lenlb < nvars lb = [lb; lb(end)*ones(nvars-lenlb,1)]; lenlb = nvars; end if lenub > nvars warning('gads:VALIDATE:extraRange','Length of upper range is > number of variables; ignoring extra bounds.'); ub = ub(1:nvars); lenub = nvars; elseif lenub < nvars ub = [ub; ub(end)*ones(nvars-lenub,1)]; lenub = nvars; end % Check feasibility of bounds len = min(lenlb,lenub); if any( lb( (1:len)' ) > ub( (1:len)' ) ) count = full(sum(lb>ub)); if count == 1 msg=sprintf(['\nExiting due to infeasibility: %i lower range exceeds the' ... ' corresponding upper range.\n'],count); else msg=sprintf(['\nExiting due to infeasibility: %i lower range exceed the' ... ' corresponding upper range.\n'],count); end error('gads:validate:infesibleRange',msg); end % check if -inf in ub or inf in lb if any(eq(ub, -inf)) error('gads:VALIDATE:infRange','-Inf detected in upper bound: upper bounds must be > -Inf.'); elseif any(eq(lb,inf)) error('gads:VALIDATE:infRange','+Inf detected in lower bound: lower bounds must be < Inf.'); end options.PopInitRange = [lb,ub]'; %------------------------------End of rangeCorrection -------------------------- function populationCheck(options) %Perform some check if Population type is double or bitString if strcmpi(options.PopulationType,'custom') return; end if ~isnumeric(gaoptimget(options,'InitialPopulation')) error('gads:VALIDATE:invalidPopulation','Invalid value for OPTIONS parameter InitialPopulation.'); end if ~isnumeric(gaoptimget(options,'InitialScores')) error('gads:VALIDATE:invalidScores','Invalid value for OPTIONS parameter InitialScores.'); end %------------------------------End of populationCheck --------------------------