I am very new to OOP in Matlab. Let's say I have a super class with one property, X. Next I want to define subclasses that has properties V, A, and B, where V is some manipulation of X, with four options:
V = A1*X - B1;
V = A1*X - B2;
V = A2*X - B1;
V = A2*X - B2;
In the actual code the options are something completely different, and it takes quite some time to calculate V, so once it is calculated I definitely want to store it. (In fact my options for A and B are actually discrete choices, so there are really just four possible combinations).
So what I did is: I created a subclass, VClass, with properties A, B, V (and X).
The SuperClass has methods:
function obj = SuperClass(X)
obj.XX = XX;
end
function add_V(obj,A,B)
if A == A1 && B == B1;
obj.A1B1 = VClass();
obj.A1B1.init_V(X,A,B);
elseif A == A2 && B == B1;
obj.A2B1 = VClass();
obj.A2B1.init_V(X,A,B);
et cetera...
end
The VClass has method:
function init_V(obj,X,A,B)
obj.V = A*X - B;
obj.A = A;
obj.B = B;
obj.X = X;
end
The thing that I don't like is that I created subclasses with names A1B1, A1B2, A2B1, and A2B2, so in every method I repeat a lot of code. I suppose I could use 'eval' with creation of a name for the subclass:
if A == A1 && B == B1;
name = 'A1B1';
.....
and in combination with:
eval(['obj.',name,' = VClass();']);
eval(['obj.',name,'.init_V(X,A,B);']);
But I am not too happy about that either, since it makes the code difficult to read.
Does anybody have another suggestion? (and any other comments of course also very welcome, since I just started with OOP)
Related
I was wondering how to call a function handle with an vector of inputs - rather than the list of aguments.
So if I have a function handle which is defined: (I guess it will be clear that I am working on fitting functions here)
fitFunctionHandle = #(a1, wG1, x1,a2, wG2, x2, c, x)(FitGaussianFn(x, [a1, 0, wG1, x1]) +FitGaussianFn(x, [a2, 0, wG2, x2]) + c
And I have an vector of inputs to hand to it
a1Init = 1
wG1Init = 2
x1Init = 3
a2Init = 4
wG2Init = 5
x2Init = 6
a2Init = 7
x = 8
%startPoint = [a1Init, wG1, x1,a2, wG2, x2, c]
inputArray = [a1Init, wG1, x1,a2, wG2, x2, c, x]
How do I call it with the vector startPoint as the input. If I try (for example)
>> fitFunctionHandle(inputArray)
I get an error:
Not enough input arguments.
That makes sense since it is expecting 8 inputs rather than a 8 element vector - but I'm wondering whether there is a way of calling it like that. I think for example in python you can convert an array to a list or something.
I'm aware that I could simplify things in this example case where I have a list of known inputs so I could just do:
fitFunctionHandle(a1Init, wG1, x1,a2, wG2, x2, c, x)
or
fitFunctionHandle(inputArray(1),inputArray(2),inputArray(3,inputArray(4), inputArray(5), inputArray(6),inputArray(7),inputArray(8))
BUT! I guess I'm trying to allow for expansion where I don't know how many arguments there would be.
For bonus points (again since I'm working on fitting functions) - It would be cool to know how to call it when x is a vector as well. I suspect that I would be doing something like
arrayfunc(fitFunctionHandle([startPoint,x]), xVector)
Thanks in advance for your help.
If I understand correctly, you are looking for a way to pass a variable number of input arguments to an anonymous function.
Take a look at this example:
anonymousFunction = #(varargin)(image(varargin{:}));
x = [5 8];
y = [3 6];
C = [0 2 4 6; 8 10 12 14; 16 18 20 22];
input = {C};
anonymousFunction(input{:});
input = {x,y,C};
anonymousFunction(input{:});
You can see in the example that a variable number of inputs is used for calling the anonymous function. Of course, this depends on the actual function that is using the arguments (in this case, image)
Regarding the varargin, the general idea was already presented in UnbearableLightness' answer. I just wanted to address your specific case.
It seems, you want to have some dynamic linear combinations of your FitGaussianFn calls with varying parameters, resulting in some complex function handle. For variable amount of terms, I would recommend to write a separate function to generate the final function handle. I made up a small toy example.
That's my fitFunctionHandle.m function:
function h = fitFunctionHandle(varargin)
n = numel(varargin);
if (n < 2)
error('Not enough input arguments.');
end
% Last input argument is considered t
t = varargin{end};
h = #(x) 0;
for iArg = 1:n-1
a = varargin{iArg}(1);
b = varargin{iArg}(2);
h = #(x) h(x) + (a*sin(b*x+t));
end
end
Each input argument consists of two parameters, that form a sin term. An additional shift parameter t is always passed at last.
And, here's some test script:
% Set up parameters
a1 = 1; b1 = 1;
a2 = 2; b2 = 2;
a3 = 3; b3 = 3;
t = pi/16;
% Evaluation point
x = pi/4;
% Compare results with explicit function calls
h = fitFunctionHandle([a1, b1], t);
res = h(x)
cmp = sin(x+t)
h = fitFunctionHandle([a1, b1], [a2, b2], t);
res = h(x)
cmp = sin(x+t) + 2*sin(2*x+t)
h = fitFunctionHandle([a1, b1], [a2, b2], [a3, b3], t);
res = h(x)
cmp = sin(x+t) + 2*sin(2*x+t) + 3*sin(3*x+t)
You see, it doesn't matter, how many parameter vectors are passed.
The output reveals, that the passed function handles are correct:
res = 0.83147
cmp = 0.83147
res = 2.7930
cmp = 2.7930
res = 4.4598
cmp = 4.4598
Regarding your last question, let's see this test:
% Set up array of t parameters, and get set of function handles
t = [pi/16, pi/8, pi/4];
hh = arrayfun(#(x) fitFunctionHandle([a1, b1], x), t, 'UniformOutput', false);
% Compare results with explicit function calls
for iH = 1:numel(hh)
h = hh{iH};
res = h(x)
cmp = sin(x + t(iH))
end
Here, the t, which is used for all sin terms in fitFunctionHanle, is a vector. The arrayfun call will return a cell array of function handles. Again, the output shows comparable results:
res = 0.83147
cmp = 0.83147
res = 0.92388
cmp = 0.92388
res = 1
cmp = 1
Hope that helps!
I'm trying to write a recursive multigrid algorithm in MATLAB.
I need to store the values of v and TC at each of the levels I'm going through to use when I'm no longer in the recursion by just calling them, in a similar way v{L} would have worked for example if I did a for loop.
Any help is much appreciated. Thank you.
function x = vcycle1d(n, x, b, T, w, levels)
x = damped_jacobiM(w, x, T, b, 10^-7, 3);
res = b - T*x;
k = log2(n+1);
N = 2^(k-1)-1;
RE = zeros(N,n);
for i = 1:N
RE(i,2*i-1:2*i+1) = [1 2 1];
end
RE = RE/4;
II = 2*RE';
TC = RE * T * II;
v = zeros(N, 1);
for i = 1:N
v(i) = (res(2*i-1) + 2*res(2*i) + res(2*i+1))/4;
end
if levels ~= 1
err= vcycle1d(N, zeros(length(v), 1), v, TC, w, levels-1);
else
err = TC\v;
end
There are two ways to do this.
Option 1: Use a persistent variable. This allows you to store details in a variable that retains values between calls.
The pros of this are that you can use it to "remember" all sorts of things from previous calls.
The cons of this are that you'll need to manage that memory in some sensible way.
Option 2: Use additional, optional, inputs.
function x = vcycle1d(n, x, b, T, w, levels, varargin)
if nargin == 7
priordetails = varargin{1};
end
currentdetails = ... ;
....
err= vcycle1d(N, zeros(length(v), 1), v, TC, w, levels-1, currentdetails);
I have a function in matlab:
function output = myfunc(a,b,c,d,e)
%a and b are mandetory
%c d and e are optional
end
How would I handle inputs if a user gave an optional arg for e but not for c and d?
nargin just gives the number of arguments. would exist be the best way?
Just use nargin. It will tell you how many arguments are present. Use varargin only when you have a variable number of arguments, that is you have no limit in number of arguments, or you want to access the arguments in an indexing fashion. I assume this is not the case for you, so one solution might look like this.
function output = myfunc(a,b,c,d,e)
%a and b are mandetory
%c d and e are optional
if nargin < 3 || isempty(c)
c = <default value for c>
end
if nargin < 4 || isempty(d)
d = <default value for d>
end
if nargin < 5 || isempty(e)
e = <default value for e>
end
<now do dome calculation using a to e>
<If a or b is accessed here, but not provded by the caller an error is generated by MATLAB>
If the user does not want to provide a value for c or d but provides e, he has to pass [], e.g. func(a,b,c,[],e), to omit d.
Alternatively you could use
if nargin == 5
<use a b c d and e>
elseif nargin == 2
<use a and b>
else
error('two or five arguments required');
end
to check if all a arguments e are present. But this requires exactly 2 or 5 arguments.
You can to define c, d and e as optional and then assign values based on position. This requires empty inputs if they want e but not c. For example:
function output = myfunc( a, b, varargin )
optionals = {0,0,0}; % placeholder for c d e with default values
numInputs = nargin - 2; % a and b are required
inputVar = 1;
while numInputs > 0
if ~isempty(varargin{inputVar})
optionals{inputVar} = varargin{inputVar};
end
inputVar = inputVar + 1;
numInputs = numInputs - 1;
end
c = optionals{1};
d = optionals{2};
e = optionals{3};
output = a + b + c + d + e;
This will just add everything together. There is alot of error checking that needs to happen with this. A better approach might be inputParser. This does paired inputs and checking. See Input Parser help
I have a function in MATALB that looks like the following:
function [a, b] = SumIt(I1, I2)
a = sum(I1);
b = sum(I2);
c = sum(I1/I2);
end
In the command window, I run the function but I cannot access the c variable. I know that I can do something like this [a, b, c] = SumIt(I1, I2) and access c variable. Can I access the variable c without outputting it?
The issue is that I have many outputs that are useless but I need to access them. How can I do this?
I tried with global but I got the same error.
function [a, b] = SumIt(I1, I2)
global c;
a = sum(I1);
b = sum(I2);
c = sum(I1/I2);
end
>> [a, b] = SumIt([1 4 6], [1 2 3]);
>> c
Undefined function or variable 'c'.
The only way that this can be done is to have a function script that also declares SumIt as an additional function and also declaring c to be global outside of the scope of SumIt. Consider the following test function shown below:
function [] = test_func()
global c;
function [a, b] = SumIt(I1, I2)
a = sum(I1);
b = sum(I2);
c = sum(I1/I2);
end
[t1, t2] = SumIt(6, 3);
disp(['t1 = ' num2str(t1)]);
disp(['t2 = ' num2str(t2)]);
disp(['c = ' num2str(c)]);
end
I have created a test function called test_func where we declare c to be global, but it is outside of the scope of SumIt. After, I declare SumIt as a nested function, then try and call it with some example numbers. I then display the outputs of SumIt as well as c. Since I1 = 6, I2 = 3, we should get c = 2.
This is what I get when I run test_func:
>> test_func
t1 = 6
t2 = 3
c = 2
Minor note
It looks like I1 and I2 are vectors judging from the context of your use with sum. As such, you should probably consider using the element-by-element division operator ./ if what I am interpreting is correct. Are you trying to divide each element of I1 by I2 and then summing the result? If that's the case, you need to change your function such that it becomes:
function [a, b] = SumIt(I1, I2)
a = sum(I1);
b = sum(I2);
c = sum(I1./I2);
end
How do I write an expression in Matlab code involving summation of a variable and then how do I minimize the expression?
ex. I need to minimize the following function
E= \sum_{i,j}[C_{ij}(r_{ij}) + C2_{ij}(r_{ij})^2]
I need to minimize the above expression for any values of r_{ij}s where i and j vary.
I could use the fmincon() in MATLAB but I am unable to write my expression suitably to give it as input to the fmincon().
Thanks.
Try this:
E = sum(sum( C.*r + C2.*r.^2 ));
where C, C2 and r are matrices of the same shape.
fmincon and other optimization functions do not require you to write everything as an expression, they can optimize for functions as well.
function E = criterion(r, C, C2)
e = C.*r + C2.*r.^2;
E = sum(e(:));
I'm not completely sure about the syntax required by fmincon, but I guess it's something like E = f(theta), where theta is a parameter vector you want adjusted such that E is minimal. Since I don't find your problem clearly described, I will assume your parameters are C and C2 (in the case that r are your parameters, the case is similar and simpler).
As fmincon uses a vector to store the coefficients, we need a function that takes such a vector and transforms it into the sizes required by the criterion function above.
function E = criterionRolledC(theta,r)
assert(numel(theta)==2*numel(r), 'The size of theta has to be twice the size of r');
[M N] = size(r);
C = theta(1:M*N);
C2 = theta(M*N+1:end);
C = reshape(C , M, N);
C2 = reshape(C2, M, N);
E = criterion(r,C,C2);
That way, you can make an anonymous function that easily conforms to the interface of the optimizer: #(theta)(criterionRolledC(theta,rValues)) will do when the variable rValues in your current workspace contains your r values.
In case you want the exact opposite, i.e. your parameters are r, it is simpler:
function E = criterionRolledR(theta,C,C2)
assert(numel(theta)==numel(C), 'The size of theta has to be the same size as C');
assert(all(size(C)==size(C2)), 'C and C2 need to have the same size');
[M N] = size(C);
r = reshape(theta, M, N);
E = criterion(r,C,C2);
And you can construct an anonymous function similarly to the other case.