|
3 | 3 | % Differentiator Class defining a differentiator.
|
4 | 4 | %
|
5 | 5 | % Copyright © 2022 Tamas Kis
|
6 |
| -% Last Update: 2022-08-31 |
| 6 | +% Last Update: 2022-09-10 |
7 | 7 | % Website: https://tamaskis.github.io
|
8 | 8 |
|
9 | 9 | %
|
|
15 | 15 | %
|
16 | 16 | %==========================================================================
|
17 | 17 |
|
18 |
| -classdef Differentiator |
| 18 | +classdef Differentiator < handle |
19 | 19 |
|
20 | 20 | % -----------
|
21 | 21 | % Properties.
|
22 | 22 | % -----------
|
23 | 23 |
|
24 | 24 | properties
|
25 |
| - method % (char) differentiation method |
26 |
| - hi % (1×1 double) step size for complex-step approximation |
27 |
| - hc % (1×1 double) relative step size for central difference approximation |
28 |
| - hf % (1×1 double) relative step size for forward difference approximation |
29 |
| - hf2 % (1×1 double) relative step size for calculating Hessian using forward difference approximation |
30 | 25 | derivative % (1×1 function_handle) derivative of a univariate, vector-valued function
|
31 | 26 | partial % (1×1 function_handle) partial derivative of a multivariate, vector-valued function
|
32 | 27 | gradient % (1×1 function_handle) gradient of a multivariate, scalar-valued function
|
33 | 28 | directional % (1×1 function_handle) directional derivative of a multivariate, scalar-valued function
|
34 | 29 | jacobian % (1×1 function_handle) Jacobian of a multivariate, vector-valued function
|
35 | 30 | hessian % (1×1 function_handle) Hessian of a multivariate, scalar-valued function
|
36 | 31 | vechessian % (1×1 function_handle) vector Hessian of a multivariate, vector-valued function
|
| 32 | + method % (char) differentiation method |
| 33 | + hi % (1×1 double) step size for complex-step approximation (defaults to 10⁻²⁰⁰) |
| 34 | + hc % (1×1 double) relative step size for central difference approximation (defaults to ε¹ᐟ³) |
| 35 | + hf % (1×1 double) relative step size for forward difference approximation (defaults to √ε) |
| 36 | + hf2 % (1×1 double) relative step size for calculating Hessian using forward difference approximation (defaults to ε¹ᐟ³) |
37 | 37 | end
|
38 | 38 |
|
39 |
| - % -------- |
40 |
| - % Methods. |
41 |
| - % -------- |
| 39 | + % --------------- |
| 40 | + % Public methods. |
| 41 | + % --------------- |
42 | 42 |
|
43 |
| - methods |
| 43 | + methods (Access = public) |
44 | 44 |
|
45 |
| - % ------------ |
46 |
| - % Constructor. |
47 |
| - % ------------ |
48 |
| - |
49 |
| - function obj = Differentiator(method,hi,hc,hf,hf2) |
50 |
| - % obj = Differentiator(method,hi,hc,hf,hf2) |
| 45 | + function obj = Differentiator(method) |
| 46 | + % obj = Differentiator(method) |
51 | 47 | %
|
52 | 48 | % Constructor.
|
53 | 49 | %--------------------------------------------------------------
|
|
59 | 55 | % 'central difference', 'complex-step', or
|
60 | 56 | % 'forward difference' (defaults to
|
61 | 57 | % 'central difference')
|
62 |
| - % hi - (OPTIONAL) (1×1 double) step size for |
63 |
| - % complex-step approximation (defaults to 10⁻²⁰⁰) |
64 |
| - % hc - (OPTIONAL) (1×1 double) relative step size for |
65 |
| - % central difference approximation (defaults to |
66 |
| - % ε¹ᐟ³) |
67 |
| - % hf - (OPTIONAL) (1×1 double) relative step size for |
68 |
| - % forward difference approximation (defaults to √ε) |
69 |
| - % hf2 - (OPTIONAL) (1×1 double) relative step size for |
70 |
| - % calculating Hessian using forward difference |
71 |
| - % approximation (defaults to ε¹ᐟ³) |
72 | 58 | %
|
73 | 59 | % -------
|
74 | 60 | % OUTPUT:
|
|
78 | 64 | %--------------------------------------------------------------
|
79 | 65 |
|
80 | 66 | % defaults "method" to 'central difference' if not input
|
81 |
| - if (nargin < 1) || isempty(method) |
82 |
| - method = 'central difference'; |
| 67 | + if (nargin == 0) || isempty(method) |
| 68 | + obj.method = 'central difference'; |
| 69 | + else |
| 70 | + obj.method = method; |
83 | 71 | end
|
84 | 72 |
|
85 |
| - % defaults "hi" to 10⁻²⁰⁰ if not input |
86 |
| - if (nargin < 2) || isempty(hi) |
87 |
| - hi = 1e-200; |
88 |
| - end |
| 73 | + % default step sizes |
| 74 | + obj.hc = eps^(1/3); |
| 75 | + obj.hi = 1e-200; |
| 76 | + obj.hf = sqrt(eps); |
| 77 | + obj.hf2 = eps^(1/3); |
89 | 78 |
|
90 |
| - % defaults "hc" to ε¹ᐟ³ if not input |
91 |
| - if nargin == 2 || isempty(hc) |
92 |
| - hc = eps^(1/3); |
93 |
| - end |
| 79 | + % sets up differentiation functions |
| 80 | + obj.set_differentiation_functions; |
94 | 81 |
|
95 |
| - % defaults "hf" to √ε if not input |
96 |
| - if nargin == 2 || isempty(hf) |
97 |
| - hf = sqrt(eps); |
98 |
| - end |
| 82 | + end |
| 83 | + |
| 84 | + function obj = set_step_size(obj,h) |
| 85 | + % Differentiator.set_step_size(h) |
| 86 | + % |
| 87 | + % Sets the step size. |
| 88 | + %-------------------------------------------------------------- |
| 89 | + % |
| 90 | + % ------ |
| 91 | + % INPUT: |
| 92 | + % ------ |
| 93 | + % h - (1×1 double) step size (for complex-step |
| 94 | + % approximation) OR relative step size (for central |
| 95 | + % and forward difference approximations) |
| 96 | + % |
| 97 | + %-------------------------------------------------------------- |
99 | 98 |
|
100 |
| - % defaults "hf2" to ε¹ᐟ³ if not input |
101 |
| - if nargin == 2 || isempty(hf2) |
102 |
| - hf2 = eps^(1/3); |
| 99 | + % step size for complex-step approximation |
| 100 | + if strcmpi(obj.method,'complex-step') |
| 101 | + obj.hi = h; |
| 102 | + |
| 103 | + % relative step size for central difference approximation |
| 104 | + elseif strcmpi(obj.method,'central difference') |
| 105 | + obj.hc = h; |
| 106 | + |
| 107 | + % relative step sizes for forward-difference approximation |
| 108 | + else |
| 109 | + obj.hf = h; |
| 110 | + obj.hf2 = h; |
| 111 | + |
103 | 112 | end
|
104 | 113 |
|
| 114 | + % updates differentiation functions |
| 115 | + obj.set_differentiation_functions; |
| 116 | + |
| 117 | + end |
| 118 | + |
| 119 | + end |
| 120 | + |
| 121 | + % --------------- |
| 122 | + % Private methods. |
| 123 | + % --------------- |
| 124 | + |
| 125 | + methods (Access = private) |
| 126 | + |
| 127 | + function obj = set_differentiation_functions(obj) |
| 128 | + % Differentiator.set_differentiation_functions |
| 129 | + % |
| 130 | + % Sets up the differentiation functions. |
| 131 | + %-------------------------------------------------------------- |
| 132 | + |
105 | 133 | % sets up differentiation functions
|
106 |
| - if strcmpi(method,'central difference') |
107 |
| - obj.derivative = @(f,x) cderivative(f,x,hc); |
108 |
| - obj.partial = @(f,x,k) cpartial(f,x,k,hc); |
109 |
| - obj.gradient = @(f,x) cgradient(f,x,hc); |
110 |
| - obj.directional = @(f,x,v) cdirectional(f,x,v,hc); |
111 |
| - obj.jacobian = @(f,x) cjacobian(f,x,hc); |
112 |
| - obj.hessian = @(f,x) chessian(f,x,hc); |
113 |
| - obj.vechessian = @(f,x) cvechessian(f,x,hc); |
114 |
| - elseif strcmpi(method,'complex-step') |
115 |
| - obj.derivative = @(f,x) iderivative(f,x,hi); |
116 |
| - obj.partial = @(f,x,k) ipartial(f,x,k,hi); |
117 |
| - obj.gradient = @(f,x) igradient(f,x,hi); |
118 |
| - obj.directional = @(f,x,v) idirectional(f,x,v,hi); |
119 |
| - obj.jacobian = @(f,x) ijacobian(f,x,hi); |
120 |
| - obj.hessian = @(f,x) ihessian(f,x,hi,hc); |
121 |
| - obj.vechessian = @(f,x) ivechessian(f,x,hi,hc); |
122 |
| - elseif strcmpi(method,'forward difference') |
123 |
| - obj.derivative = @(f,x) fderivative(f,x,hf); |
124 |
| - obj.partial = @(f,x,k) fpartial(f,x,k,hf); |
125 |
| - obj.gradient = @(f,x) fgradient(f,x,hf); |
126 |
| - obj.directional = @(f,x,v) fdirectional(f,x,v,hf); |
127 |
| - obj.jacobian = @(f,x) fjacobian(f,x,hf); |
128 |
| - obj.hessian = @(f,x) fhessian(f,x,hf2); |
129 |
| - obj.vechessian = @(f,x) fvechessian(f,x,hf2); |
| 134 | + if strcmpi(obj.method,'central difference') |
| 135 | + obj.derivative = @(f,x) cderivative(f,x,obj.hc); |
| 136 | + obj.partial = @(f,x,k) cpartial(f,x,k,obj.hc); |
| 137 | + obj.gradient = @(f,x) cgradient(f,x,obj.hc); |
| 138 | + obj.directional = @(f,x,v) cdirectional(f,x,v,obj.hc); |
| 139 | + obj.jacobian = @(f,x) cjacobian(f,x,obj.hc); |
| 140 | + obj.hessian = @(f,x) chessian(f,x,obj.hc); |
| 141 | + obj.vechessian = @(f,x) cvechessian(f,x,obj.hc); |
| 142 | + elseif strcmpi(obj.method,'complex-step') |
| 143 | + obj.derivative = @(f,x) iderivative(f,x,obj.hi); |
| 144 | + obj.partial = @(f,x,k) ipartial(f,x,k,obj.hi); |
| 145 | + obj.gradient = @(f,x) igradient(f,x,obj.hi); |
| 146 | + obj.directional = @(f,x,v) idirectional(f,x,v,obj.hi); |
| 147 | + obj.jacobian = @(f,x) ijacobian(f,x,obj.hi); |
| 148 | + obj.hessian = @(f,x) ihessian(f,x,obj.hi,obj.hc); |
| 149 | + obj.vechessian = @(f,x) ivechessian(f,x,obj.hi,obj.hc); |
| 150 | + elseif strcmpi(obj.method,'forward difference') |
| 151 | + obj.derivative = @(f,x) fderivative(f,x,obj.hf); |
| 152 | + obj.partial = @(f,x,k) fpartial(f,x,k,obj.hf); |
| 153 | + obj.gradient = @(f,x) fgradient(f,x,obj.hf); |
| 154 | + obj.directional = @(f,x,v) fdirectional(f,x,v,obj.hf); |
| 155 | + obj.jacobian = @(f,x) fjacobian(f,x,obj.hf); |
| 156 | + obj.hessian = @(f,x) fhessian(f,x,obj.hf2); |
| 157 | + obj.vechessian = @(f,x) fvechessian(f,x,obj.hf2); |
130 | 158 | end
|
131 | 159 |
|
132 |
| - % sets method and step sizes as properties so they may be |
133 |
| - % queried/edited |
134 |
| - obj.method = method; |
135 |
| - obj.hc = hc; |
136 |
| - obj.hi = hi; |
137 |
| - obj.hf = hf; |
138 |
| - obj.hf2 = hf2; |
139 |
| - |
140 | 160 | end
|
141 | 161 |
|
142 | 162 | end
|
|
0 commit comments