Asked by Lukas
on 25 Jul 2014

I use the Matlab Inputparser Class to validate function input, this is a minimal example:

function C = multiplyMatrix(A, B) p = inputParser; addRequired(p, 'A', @isnumeric); % Line A addRequired(p, 'B', @isnumeric); parse(p, A, B);

if size(A, 2) ~= size(B, 1) % Line B error('Size mismatch.'); end

C = A*B; end

How do I integrate tests spanning more than one variable (i.e. the if-statement in Line B) in the concept of the Matlab Inputparser Class? I only found out how to create tests regarding one variable (see Line A).

I am also happy about comments about the usage of this Parser in total.

(I had asked this question on stackoverflow.com before, but I feel like this is the better place to ask.)

Answer by Dima Lisin
on 26 Jul 2014

Accepted Answer

Unfortunately, you cannot do that inside `inputParser`. For each parameter you can only supply a function that validates just that parameter. Any tests involving more than one parameter have to be done separately, after you call `parse()`.

Dima Lisin
on 26 Jul 2014

I beg to disagree. This is not a bug. It is a limitation of `inputParser`. It treats each parameter independently, and any validation that spans multiple parameters must be done separately. For example, the code you've posted does the job.

The reason `inputParser` treats each parameter separately is that it makes for a simple and clean interface. If you were to allow validators that take multiple parameters how would you do it?

Let's look at a more complex situation. Let's say we have required parameters A and B, and also a name-value pair 'C':

function C = multiplyMatrix(varargin) p = inputParser; addRequired(p, 'A', @isnumeric); % Line A addRequired(p, 'B', @isnumeric); addParameter(p, 'C', eye(3), @isnumeric); ... end

Let's also say that A and C must have the same size. How would you tell that to the input parser? How would you specify a single validator function for A and C? Even if this can be done, it would certainly complicate the interface, and probably introduce additional limitations. In the example above you would probably have to require that A and C must be next to each other in the argument list, which would force you to re-order the arguments.

But what if you had more complicated validation involving multiple overlapping subsets of parameters? What if A and B must have the same number of columns, and A and C must have the same number of rows? It would seem much easier to let the input parser validate them in isolation, and then implement the complicated validation separately.

`inputParser` is very useful, because it saves you the trouble of parsing optional parameters and name-value pairs. But if you have complicated validation logic, you have to code that yourself. By the way it is always a good idea to wrap the parameter parsing including `inputParser` and any custom validation code into a local function.

Lukas
on 29 Jul 2014

The `inputParser` is indeed very useful. Since the errors are clear and the notation is widely accepted, I would like to remain within the `inputParser` framework.

This is a working improvisation:

function C = multiplyMatrix(A, B) p = inputParser; A_B = {A, B}; addRequired(p, 'A', @isnumeric); addRequired(p, 'B', @isnumeric); addRequired(p, 'A_B', @(x) (size(x{1}, 2) == size(x{2}, 1))); parse(p, A, B, A_B);

C = A*B; end

This is a possible way how it could look like with the additional function `addCombination()`. The additional function would have to be applied after evaluation of all other `add*()` functions. Thus, default values can be compared within combinations as well:

function C = multiplyMatrix(A, B) p = inputParser; addRequired(p, 'A', @isnumeric); addRequired(p, 'B', @isnumeric); addCombination(p, {'A', 'B'}, @(x, y) (size(x, 2) == size(y, 1))); parse(p, A, B);

C = A*B; end

Thank you for your detailed answer.

Daniele Busi
on 16 Sep 2018 at 20:18

The suggested addCombination method can only be included inside a subclass. This subclass should do the job:

classdef inputParserEx < inputParser properties combofuncs combovars end methods function p = inputParserEx p.combofuncs = cell(0); p.combovars = cell(0); end function addCombination(p,vars,validateFunc) assert(isa(p,'inputParserEx')) assert(iscellstr(vars) && isvector(vars)) assert(isa(validateFunc,'function_handle')) assert(nargin(validateFunc) == numel(vars)); p.combofuncs{end+1} = validateFunc; p.combovars(end+1,1) = {numel(vars)}; p.combovars(end,2:numel(vars)+1) = {vars{:}}; end function parse(p,varargin) assert(isa(p,'inputParserEx')) parse@inputParser(p,varargin{:}); for c = 1:numel(p.combofuncs) args = cell(1,p.combovars{c,1}); for v = 1:p.combovars{c,1} assert(isfield(p.Results,p.combovars{c,1+v}),['invalid combination number ' num2str(c)]); args{v} = p.Results.(p.combovars{c,1+v}); end assert(p.combofuncs{c}(args{:}),['condition number ' num2str(c) ' not fulfilled']); end end end end

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.