gusucode.com > symbolic工具箱matlab源码程序 > symbolic/@sym/vpaintegral.m
function y = vpaintegral(varargin) %VPAINTEGRAL Numerical integration of symbolic expressions. % Q = VPAINTEGRAL(FUN,XMIN,XMAX) approximates the integral of function % FUN from XMIN to XMAX by variable precision arithmetic using global % adaptive quadrature and default error tolerances. % % FUN must be a symbolic expression or an array of symbolic expressions. % If FUN contains more than one symbolic variable, the input syntax % Q = VPAINTEGRAL(FUN,X,XMIN,XMAX) should be used to indicate the % variable X that serves as the integration variable. % XMIN and XMAX can be symbolic numbers or double numbers or -Inf or % Inf. If both are finite, they can be complex. If at least one is % complex, VPAINTEGRAL approximates the path integral from XMIN to % XMAX over a straight line path. % % The available options are % % 'AbsTol', absolute error tolerance % 'RelTol', relative error tolerance % % VPAINTEGRAL attempts to satisfy |Q-I|<=max(AbsTol,RelTol*|Q|), % where I denotes the exact value of the integral. Usually RelTol % determines the accuracy of the integration. However, if |Q| is % sufficiently small, AbsTol determines the accuracy of the % integration, instead. The default value of AbsTol is 1e-10, and % the default value of RelTol is 1e-6. The value of AbsTol must % be nonnegative, the value of RelTol must be positive. % % 'Waypoints', vector of integration waypoints % % If FUN has discontinuities or singularities in the interval of % integration, the locations should be supplied as a 'Waypoints' % vector. If XMIN, XMAX, or any entry of the waypoints vector is % complex, the integration is performed over a sequence of straight % line paths in the complex plane, from XMIN to the first waypoint, % from the first waypoint to the second, and so forth, and finally % from the last waypoint to XMAX. % % 'MaxFunctionCalls', maximal number of evaluations of FUN % % The numerical integration gives up and throws an error if the % number of internal FUN evaluations exceeds this value. The value % of this option must be a positive integer or Inf. The default % value is 10^5. % % If any of FUN, XMIN, XMAX, or the 'Waypoints' vector contain a % symbolic variable other than the integration variable, then a % symbolic call of VPAINTEGRAL is returned. When several symbolic % variables are present, it is recommended to use the input syntax % VPAINTEGRAL(FUN,X,XMIN,XMAX) in which the integration variable X % is explicitly specified. Higher dimensional integrals can be % computed by nested calls such as % vpaintegral(vpaintegral(FUN(X,Y),Y,YMIN(X),YMAX(X)),X,XMIN,XMAX). % % Examples: % % Integrate f(x) = exp(-x^2)*log(x)^2 from 0 to infinity. % syms x; % f = exp(-x^2)*log(x)^2; % Q = vpaintegral(f,0,Inf) % % Q = % % 1.94752 % % % Specify tolerances. % % Q = vpaintegral(sin(x)/x^3,1,Inf,'AbsTol',1e-16,'RelTol',1e-10) % % Q = % % 0.3785300171 % % % Integrate f(x) = 1/(2*x-1) in the complex plane over the % % closed triangular path from 0 to 1+1i to 1-1i to 0. The % % result changes its sign when the orientation of the path % % is reverted. % Q = vpaintegral(1/(2*x-1),0,0,'Waypoints',[1+1i,1-1i]) % % Q = % % 1.11022e-16 - 3.14159i % % Q = vpaintegral(1/(2*x-1),0,0,'Waypoints',[1-1i,1+1i]) % % Q = % % 1.11022e-16 + 3.14159i % % % Integrate the vector-valued function sin((1:5)*x) from 0 to pi. % Q = vpaintegral(sin((1:5)*x),0,pi) % % Q = % % [ 2.0, 0, 0.666667, -1.08996e-16, 0.4] % % % Use a parameter c in the integrand. The integration variable x % % is specified explicitly. The result cannot be computed % % numerically because of the symbolic parameter. % syms f(x,c) % f(x,c) = 1/(x^3-2*x-c); % Q = vpaintegral(f,x,0,2) % % Q(c) = % % vpaintegral(-1/(- x^3 + 2*x + c), x, 0, 2) % % % Multiple integration over the triangular region 0<=x<=1,|y|<x. % % syms x y; % Q = vpaintegral(vpaintegral(sin(x-y)/(x-y),y,[-x,x]),x,[0,1]) % % Q = % % 0.89734 % % See also INT, INTEGRAL, DSOLVE, VPA. % Copyright 2015 The MathWorks, Inc. narginchk(2,Inf); k = find(cellfun(@ischar, varargin), 1); if isempty(k) [fun, x, a, b] = parseFunctionVariableBounds(varargin{:}); elseif k >= 3 [fun, x, a, b] = parseFunctionVariableBounds(varargin{1:min(k-1,4)}); else % k = 2 error(message('symbolic:sym:vpaintegral:UnexpectedCharInput')); end if ~sym.isVariable(x) error(message('symbolic:sym:int:InvalidIntegrationVariable', char(x))); end p = inputParser; p.addParameter('RelTol', 1.0e-06, @(x) ~ischar(x) && isscalar(x) && isnumeric(double(x)) && logical(x>0)); p.addParameter('AbsTol', 1.0e-10, @(x) ~ischar(x) && isscalar(x) && isnumeric(double(x)) && logical(x>=0)); p.addParameter('Waypoints', sym([]), @(x) ~ischar(x) && (isempty(x) || isvector(sym(x)))); p.addParameter('MaxFunctionCalls', sym(100000), ... @(x) ~ischar(x) && isscalar(x) && (sym(x) == sym(Inf) || isPositiveInteger(sym(x)))); % Allow option 'ArrayValued' of the Core Matlab 'integral' routine, but ignore it. p.addParameter('ArrayValued', false); p.parse(varargin{k:end}); abstol = double(p.Results.AbsTol); reltol = double(p.Results.RelTol); waypoints = sym(p.Results.Waypoints); maxfuncalls = sym(p.Results.MaxFunctionCalls); fun = privResolveArgs(sym(fun)); fun = fun{1}; issymfun = isa(fun, 'symfun'); fargs = sym([]); if issymfun fargs = argnames(fun); % Eliminate x from the arguments of the symfun fargs = privsubsref(fargs, logical(fargs ~= x)); fun = formula(fun); end if isa(a, 'symfun') fargs = union(fargs, argnames(a)); a = formula(a); issymfun = true; end if isa(b, 'symfun') fargs = union(fargs, argnames(b)); b = formula(b); issymfun = true; end if isa(waypoints, 'symfun') fargs = union(fargs, argnames(waypoints)); waypoints = formula(waypoints); issymfun = true; end if isempty(a) || isempty(b) % consistent with integral(@sin, []) error(message('MATLAB:narginchk:notEnoughInputs')); end if (isinf(a) && isempty(symvar(a)) && ~isreal(a)) || ... (isinf(b) && isempty(symvar(b)) && ~isreal(b)) error(message('symbolic:sym:vpaintegral:ComplexContourMustBeFinite')); end newDigits = ceil(max(2,log10(1/reltol))); oldDigits = digits(newDigits + 2); cleanupObj = onCleanup(@() digits(oldDigits)); if (any(isnan(reshape(fun,[],1))) || isnan(a) || isnan(b)) ysym = sym(NaN); elseif ~isfinite(fun) ysym = sym(fun); else ysym = feval(symengine, 'vpaintegral', fun,... [x.s '=' a.s '..' b.s],... ['RelativeError = ' num2str(reltol/100)],... ['AbsoluteError = ' num2str(abstol)],... ['"Waypoints" = ' waypoints.s],... ['MaxCalls = ' maxfuncalls.s]); if ysym == evalin(symengine, 'FAIL') error(message('symbolic:sym:vpaintegral:IncreaseMaxFunctionCalls')) end end y = privResolveOutput(ysym, fun); % Reduce the precision of the result to reltol. Thus, % only the reliable leading digits become visible. digits(newDigits); y = vpa(y); if issymfun && ~isempty(fargs) y = symfun(y, fargs); end % end of function vpaintegral % ==================================== function [f, x, a, b] = parseFunctionVariableBounds(f, x, a, b, varargin) %parseFunctionVariableBounds Helper method for argument parsing % It assists in parsing inputs to a function S with calling syntax % S(f, 'Option',...) % S(f, x, 'Option',...) % S(f, [a b], 'Option',...) % S(f, a, b, 'Option',...) % S(f, x, [a b], 'Option',...) % S(f, x, a, b, 'Option',...) % where x defaults to symvar(f, 1). f = sym(f); x = sym(x); switch nargin case 2 [a, b] = rangeVector(x); if ~isempty(a) x = symv(f); end case 3 a = sym(a); [tmp, b] = rangeVector(a); if isa(tmp, 'symfun') tmp = formula(tmp); end if isempty(tmp) b = a; a = x; x = symv(f); else a = tmp; end case 4 a = sym(a); b = sym(b); end % ==================================== function X = symv(f) X = symvar(f, 1); if isempty(X) X = sym('x'); end % ==================================== function [a, b] = rangeVector(x) if isa(x, 'symfun') fargs = argnames(x); issymfun = true; else issymfun = false; end x = formula(x); if isvector(x) && numel(x) == 2 a = privsubsref(x,1); b = privsubsref(x,2); else a = []; b = []; end if issymfun && ~isempty(fargs) a = symfun(a, fargs); b = symfun(b, fargs); end