Mercurial > octave-nkf
comparison scripts/ode/odeget.m @ 20620:e5f36a7854a5
Remove fuzzy matching from odeset/odeget.
* levenshtein.cc: Deleted file.
* libinterp/corefcn/module.mk: Remove levenshtein.cc from build system.
* fuzzy_compare.m: Deleted file.
* scripts/ode/module.mk: Remove fuzzy_compare.m from build system
* odeget.m: Reword docstring. Use a persistent cellstr variable to keep track
of all options. Replace fuzzy_compare() calls with combination of strcmpi and
strncmpi. Report errors relative to function odeget rather than OdePkg.
Rewrite and extend BIST tests. Add input validation BIST tests.
* odeset.m: Reword docstring. Use a persistent cellstr variable to keep track
of all options. Replace fuzzy_compare() calls with combination of strcmpi and
strncmpi. Report errors relative to function odeset rather than OdePkg.
Use more meaningful variables names and create intermediate variables with
logical names to help make code readable. Remove interactive input when
multiple property names match and just issue an error. Rewrite BIST tests.
* ode_struct_value_check.m: Remove input checking for private function which
must always be invoked correctly by caller. Use intermediate variables opt and
val to make the code more understandable. Consolidate checks on values into
single if statements. Use 'val == fix (val)' to check for integer.
* __unimplemented__.m: Removed odeset, odeget, ode45 from list.
author | Rik <rik@octave.org> |
---|---|
date | Fri, 09 Oct 2015 12:03:23 -0700 |
parents | 45151de7423f |
children |
comparison
equal
deleted
inserted
replaced
20619:eef93a493ce3 | 20620:e5f36a7854a5 |
---|---|
23 ## | 23 ## |
24 ## Query the value of the property @var{field} in the ODE options structure | 24 ## Query the value of the property @var{field} in the ODE options structure |
25 ## @var{ode_opt}. | 25 ## @var{ode_opt}. |
26 ## | 26 ## |
27 ## If called with two input arguments and the first input argument @var{ode_opt} | 27 ## If called with two input arguments and the first input argument @var{ode_opt} |
28 ## is a structure and the second input argument @var{field} is a string then | 28 ## is an ODE option structure and the second input argument @var{field} is a |
29 ## return the option value @var{val} that is specified by the option name | 29 ## string specifying an option name then return the option value @var{val} |
30 ## @var{field} in the ODE option structure @var{ode_opt}. | 30 ## corresponding to to @var{field} from @var{ode_opt}. |
31 ## | 31 ## |
32 ## If called called with an optional third input argument then return the | 32 ## If called called with an optional third input argument, and @var{field} is |
33 ## default value @var{default} if @var{field} is not set in the structure | 33 ## not set in the structure @var{ode_opt}, then return the default value |
34 ## @var{ode_opt}. | 34 ## @var{default} instead. |
35 ## @seealso{odeset} | 35 ## @seealso{odeset} |
36 ## @end deftypefn | 36 ## @end deftypefn |
37 | 37 |
38 ## FIXME: 4th input argument 'opt' is undocumented. | 38 ## FIXME: 4th input argument "opt" is undocumented. |
39 | |
40 ## Note: 2006-10-22, Thomas Treichl | |
41 ## We cannot create a function of the form odeget (@var{odestruct}, | |
42 ## @var{name1}, @var{name2}) because we would get a mismatch with | |
43 ## the function form 1 like described above. | |
44 | 39 |
45 function val = odeget (ode_opt, field, default = [], opt) | 40 function val = odeget (ode_opt, field, default = [], opt) |
46 | 41 |
47 if (nargin == 1 || nargin > 4) | 42 if (nargin < 1 || nargin > 4) |
48 print_usage (); | 43 print_usage (); |
49 endif | 44 endif |
50 | 45 |
51 ## Shortcut for empty options structures | 46 ## Shortcut for empty options structures |
52 if (isempty (ode_opt)) | 47 if (isempty (ode_opt)) |
83 val = default; | 78 val = default; |
84 end_try_catch | 79 end_try_catch |
85 return; | 80 return; |
86 endif | 81 endif |
87 | 82 |
88 ## check if the given struct is a valid OdePkg struct | 83 ## Check if the given struct is a valid OdePkg struct |
89 ode_struct_value_check (ode_opt); | 84 ode_struct_value_check (ode_opt); |
90 | 85 |
91 ## define all the possible OdePkg fields | 86 ## Define all the possible OdePkg fields |
92 options = ["AbsTol"; "Algorithm"; "BDF"; "Choice"; "Eta"; "Events"; | 87 persistent options = {"AbsTol"; "Algorithm"; "BDF"; "Choice"; "Eta"; "Events"; |
93 "Explicit"; "InexactSolver"; "InitialSlope"; "InitialStep"; | 88 "Explicit"; "InexactSolver"; "InitialSlope"; |
94 "Jacobian";"JConstant";"JPattern";"Mass"; "MassConstant"; | 89 "InitialStep"; "Jacobian"; "JConstant"; "JPattern"; |
95 "MassSingular"; "MaxNewtonIterations"; "MaxOrder"; "MaxStep"; | 90 "Mass"; "MassConstant"; "MassSingular"; |
96 "MStateDependence"; "MvPattern"; "NewtonTol"; "NonNegative"; | 91 "MaxNewtonIterations"; "MaxOrder"; "MaxStep"; |
97 "NormControl"; "OutputFcn"; "OutputSave"; "OutputSel"; | 92 "MStateDependence"; "MvPattern"; "NewtonTol"; |
98 "PolynomialDegree"; "QuadratureOrder"; "Refine"; "RelTol"; | 93 "NonNegative"; "NormControl"; "OutputFcn"; "OutputSave"; |
99 "Restart"; "Stats"; "TimeStepNumber"; "TimeStepSize"; | 94 "OutputSel"; "PolynomialDegree"; "QuadratureOrder"; |
100 "UseJacobian"; "Vectorized"]; | 95 "Refine"; "RelTol"; "Restart"; "Stats"; |
96 "TimeStepNumber"; "TimeStepSize"; "UseJacobian"; | |
97 "Vectorized"}; | |
98 | |
99 exactmatch = true; | |
100 match = find (strcmpi (field, options)); | |
101 if (isempty (match)) | |
102 match = find (strncmpi (field, options, length (field))); | |
103 exactmatch = false; | |
104 endif | |
101 | 105 |
102 while (1) | 106 if (isempty (match)) |
103 pos = fuzzy_compare (field, options); | 107 if (nargin == 2) |
104 | 108 error ("odeget: invalid property '%s'", field); |
105 if (isempty (pos)) # no match for the given option | 109 else |
106 if (nargin == 2) | 110 ## FIXME: Should we warn, but complete the action, or just error out? |
107 error ("odeget: invalid property. No property found with name '%s'", | 111 warning ("odeget:InvalidArgument", |
112 "odeget: invalid property '%s'. Using supplied default value.", | |
108 field); | 113 field); |
109 endif | 114 val = default; |
115 endif | |
116 elseif (numel (match) == 1) | |
117 if (! exactmatch) | |
110 warning ("odeget:NoExactMatching", | 118 warning ("odeget:NoExactMatching", |
111 "no property found with name '%s'. ", | 119 "odeget: no exact match for '%s'. Assuming '%s'.\n", |
112 "Assuming default value.", field); | 120 field, options{match}); |
121 endif | |
122 val = []; | |
123 try | |
124 val = ode_opt.(options{match}); | |
125 end_try_catch | |
126 if (isempty (val)) | |
113 val = default; | 127 val = default; |
114 return; | |
115 endif | 128 endif |
116 | 129 else |
117 if (rows (pos) == 1) # one matching | 130 error ("odeget: no exact match for '%s'. Possible fields found: %s.", |
118 if (! strcmp (lower (deblank (field)), | 131 field, strjoin (options(match), ", ")); |
119 lower (deblank (options(pos,:)))) ) | 132 endif |
120 warning ("odeget:InvalidArgument", | |
121 "no exact matching for '%s'. ", | |
122 "Assuming you were intending '%s'.", | |
123 field, deblank (options(pos,:))); | |
124 endif | |
125 val = ode_opt.(deblank (options(pos,:))); | |
126 if (isempty (val)) | |
127 val = default; | |
128 endif | |
129 return; | |
130 endif | |
131 | |
132 ## FIXME: Do we really need interactive selection? | |
133 ## Matlab doesn't appear to offer this. | |
134 ## if there are more matching, ask the user to be more precise | |
135 warning ("OdePkg:InvalidArgument", | |
136 "no exact matching for '%s'. %d possible fields were found.", | |
137 field, rows (pos)); | |
138 for j = 1:(rows (pos)) | |
139 printf ("%s\n", deblank (options(pos(j),:))); | |
140 endfor | |
141 do | |
142 printf ("Please insert field name again.\n"); | |
143 field = input ("New field name: "); | |
144 until (ischar (field)) | |
145 endwhile | |
146 | 133 |
147 endfunction | 134 endfunction |
148 | 135 |
149 | 136 |
150 %!demo | 137 %!demo |
153 %! # empty matrix value would have been returned. | 140 %! # empty matrix value would have been returned. |
154 %! | 141 %! |
155 %! A = odeset ("RelTol", 1e-1, "AbsTol", 1e-2); | 142 %! A = odeset ("RelTol", 1e-1, "AbsTol", 1e-2); |
156 %! odeget (A, "RelTol", []) | 143 %! odeget (A, "RelTol", []) |
157 | 144 |
158 %!test | 145 %!assert (odeget (odeset (), "RelTol"), []) |
159 %! wstate = warning ("off", "OdePkg:InvalidArgument"); | 146 %!assert (odeget (odeset ("RelTol", 10), "RelTol"), 10) |
160 %! unwind_protect | 147 %!assert (odeget (odeset (), "RelTol", 10), 10) |
161 %! assert (odeget (odeset (), "RelTol"), []); | 148 %!assert (odeget (odeset (), "Stats"), []) |
162 %! assert (odeget (odeset (), "RelTol", 10), 10); | 149 %!assert (odeget (odeset (), "Stats", "on"), "on") |
163 %! assert (odeget (odeset (), "Stats"), []); | 150 %!assert (odeget (odeset (), "Mass"), []) |
164 %! assert (odeget (odeset (), "Stats", "on"), "on"); | 151 %!assert (odeget (odeset (), "AbsTol", 1e-6, "fast"), []) |
165 %! assert (odeget (odeset (), "AbsTol", 1e-6, "fast"), []); | 152 %!assert (odeget (odeset (), "AbsTol", 1e-6, "fast_not_empty"), 1e-6) |
166 %! assert (odeget (odeset (), "AbsTol", 1e-6, "fast_not_empty"), 1e-6); | 153 %!assert (odeget (odeset (), "AbsTol", 1e-9), 1e-9) |
167 %! assert (odeget (odeset (), "AbsTol", 1e-9), 1e-9); | |
168 %! unwind_protect_cleanup | |
169 %! warning (wstate); | |
170 %! end_unwind_protect | |
171 | 154 |
155 %!error odeget () | |
156 %!error odeget (1) | |
157 %!error odeget (1,2,3,4,5) | |
158 %!error <ODE_OPT must be a valid ODE_STRUCT> odeget (1, "opt1") | |
159 %!error <FIELD must be a string> odeget (struct ("opt1", 1), 1) | |
160 %!error <invalid property 'foo'> odeget (struct ("opt1", 1), "foo") | |
161 %!warning <Using supplied default value> odeget (struct ("opt1", 1), "foo", 3); | |
162 %!warning <no exact match for 'Rel'. Assuming 'RelTol'> odeget (struct ("RelTol", 1), "Rel"); | |
163 %!error <Possible fields found: InitialSlope, InitialStep> odeget (odeset (), "Initial") | |
164 |