vectorize a function with multiple variables - matlab

Consider the arbitrary function:
function myFunc_ = myFunc(firstInput, secondInput)
myFunc_ = firstInput * secondInput;
end
Now imagine I want to map the above function to an array for the first input firstInput, while the second input secondInput is constant. For example, something like:
firstVariable = linspace(0., 1.);
plot(firstVariable, map(myFunc, [firstVariable , 0.1]))
where 0.1 is an arbitrary scalar value for the secondInput and firstVariable array is an arbitrary array for the firstInput.
I have looked into the arrayfun() function. However, I don't know how to include the constant variable. Plus it seems like the syntax between MATLAB and Octave are different, or maybe I'm mistaken. It is important for me to have a cross-compatible code that I can share with colleagues.

Assuming in the original function you were multiplying two scalars and you want to vectorise, then
function myFunc_ = myFunc(firstInput, secondInput)
myFunc_ = firstInput .* secondInput;
end
should work just fine.
Then plot it directly:
plot( firstVariable, myFunc(firstVariable , 0.1) )

I'm afraid the arbitrary examples given in the original question were too simplified and as a result, they do not represent the actual issue I'm facing with my code. But I did manage to find the right syntax that works inside Octave:
plot(firstVariable, arrayfun(#(tempVariable) myFunc(tempVariable, 0.1), firstVariable))
basically the
#(tempVariable) myFunc(tempVariable, 0.1)
creates what is so-called an anonymous function and the
arrayfun(<function>, <array>)
maps the function over the given array.

Related

MATLAB: Using get in cellfun for a cell array of objects

I've been stuck with this for a while and I couldn't find something similar asked previously (or I have failed in doing so)
My situation is fairly simple: I have a cell array of objects. They are all the same object and I have a get function for this kind of object which is: get (obj, attr), where obj is the object in question and attr is a integer from 1-6. Depending on the number the get function returns the corresponding attribute.
I would like to obtain all of my "position" attributes from all my objects which are in the corresponding cell array (this would be attr = 2). I know that cellfun performs a function on all cells, but the question is, how do I use my get function here for all my objects, taking into account that the function is get (obj, attr) ?
Thanks in advance
Firstly, by using get as a custom function you are shadowing the built-in get function - this is bad practise!
With this in mind, and to avoid confusion with the built-in get function which has similar syntax, I'm going to use getattr as a stand-in for your custom function which accpets an object and an integer 1 to 6.
pos = cellfun( #(obj) getattr( obj, 2 ), myCellOfObjects, 'uni', 0 );
By specifying 'uni', 0, the output doesn't have to be scalar and will be put into a cell array. This is useful when, for example, you have a multi-element array for your position.
This is equivalent to the following loop:
pos = cell( numel(myCellOfObjects), 1 );
for ii = 1:numel(pos)
pos{ii} = getattr( myCellOfObjects{ii}, 2 );
end
If ever in doubt about cellfun or arrayfun, just write a loop first - they are essentially the same but more concise.
There is a trick to this some are unaware of: you can pass multiple arguments to cellfun like this:
cellfun(#(obj,attr) get(obj,attr), {obj1,obj2},{attr1,attr2},'uni',0)
if you want to get one attribute of the cellarray (instead of providing an attribute for every object in the cellarray), then you can simply use this
cellfun(#(x) getattr(x,attr),obj,'uni',0)
put into anonymous function for convenience:
get_attr = #(obj,attr) cellfun(#(x) getattr(x,attr),obj,'uni',0)
%use:
get_attr(obj_in_cellarray,'myattribute')
%returns cell array of object attributes
I haven't run any of these functions since you didn't provide any example data / code. Please test and feedback.

Writing superficial wrappers for functions [MATLAB]

I have a function in Matlab:
function [runs,balls]=batting(form,team_flag,weather_flag)
form is a 1x13 array of doubles. The flags are just boolean. runs,balls are just scalars. The function above does some complex mathematical simulation to arrive at its output values. Now i write a wrapper :
function [runs,balls]=wrapper1(form)
[runs,balls]=batting(form,false,false);
Then I write another wrapper:
function runs_vector=wrapper2(form_vector)
for i=1:size(form_vector,1)
form_cell{i}=form_vector(i,:);
end
runs_vector=cellfun(#wrapper1, form_cell)';
It must be evident as to what i am trying to achieve. I am trying to exploit the behavior of cellfun for my custom-defined function batting. The flag arguments need to be set to false here but in general they are varied in the project of which this is part of. So i could not disappear the flag inputs to the batting function without writing an intermediate wrapper,i.e. wrapper1. My question is if there is a less ugly or more smart way of doing this?
You can eliminate wrapper1 by creating an anonymous function that reduces batting to two arguments:
runs_vector = cellfun(#(form) batting(form, false, false), form_cell)';
In addition, the loop can be replaced by num2cell like so:
form_cell = num2cell(form_vector, 2);
Combining these two gives us
function runs_vector = wrapper2(form_vector)
form_cell = num2cell(form_vector, 2);
runs_vector = cellfun(#(form) batting(form, false, false), form_cell)';

minFunc package usage

I have been using MATLAB fminunc function to solve my optimization problem. I want to try the minFunc package :
http://www.di.ens.fr/~mschmidt/Software/minFunc.html
When using fminunc, I defined a function funObj.m which gives me the objective value and the gradient at any point 'x'. It also takes in several external inputs say, {a,b,c} which are matrices. So the function prototype looks like :
function [objVal,G] = funObj(x,a,b,c)
I want to use the same setup in the minFunc package. From the examples, I figured this should work :
options.Method='lbfgs';
f = #(x)funObj(x,a,b,c);
x = minFunc(f,x_init,options);
But when I call this way, I get an error as:
Error using funObj
Too many output arguments.
What is the correct way to call minFunc for my case?
**EDIT : Alright, here is a sample function that I want to use with minFunc. Lets say I want to find the minimum of a*(b-x)^2, where a,b are scalar parameters and x being a scalar too. The MATLAB objective function will then look like :
function obj = testFunc(x,a,b)
obj = a*(b-x)^2;
The function call to minimize this using fminunc (in MATLAB ) is simply:
f = #(x)testFunc(x,a,b);
x = fminunc(f,x_init);
This gives me the minimum of x = 10. Now, How do I do the same using minFunc ?
"Note that by default minFunc assumes that the gradient is supplied, unless the 'numDiff' option is set to 1 (for forward-differencing) or 2 (for central-differencing)."
The error is because only one argument is returned by the function. You can either return the gradient as a second argument or turn on numerical differencing.
Agree with Mark. I think the simplest way to solve it is
minFunc(#testFunc, x_init, a, b, c)
In MATLAB temporary function can only have one return value. So f = #(x)testFunc(x,a,b); let your method drop gradient part every time. Because minFunc can accept extra paramters, you can pass a, b and c after x_init. I think this would work.

matlab How to use a textstring as input parameter in functions

I would like to use a dataset filename "AUDUSD" in several functions. It would be easier for me, just to change the filename "AUDUSD" to a more general name like "FX" and then using the abbreviation "FX" in other_matlab functions, e.g. double(). But matlab does not know the name "FX" (that should be assigned to the dataset "AUDUSD") in the code below... Any suggestions?
CODE:
FX = 'AUDUSD';
load(FX); %OKAY !!! FX works as input to open file AUDUSD!
Svars = {'S_bid','S_offer'};
Fvars = {'F_bid','F_offer'};
vS = double(FX,Svars); % FX does NOT work as input for the file AUDUSD
There is no double() function that accepts multiple cell arrays as arguments (this is what happens when you call double(FX,Svars)).
If you call double(FX), then each character in FX is interpreted for its ASCII value and then cast to double. So you get [ 65.0 85.0 68.0 85.0 83.0 68.0 ]. This is the behavior for the double() function if you provide a vector: each individual value in the vector is cast to double.
You'd have to provide more details on what you're trying to accomplish to give any more suggestions.
I have a different example, maybe you will better understand my point. The key work I would like to process is as follows:
I have got a folder with "dataset" files. I would like to loop through this folder, entering in any datasetfile, extracting the 2nd and 3rd column of each dataset file, and constructing only ONE new datasetfile with all 2nd and 3rd columns of the datasetfiles.
One problem is that the size of the datasetfiles are not the same, so I tried to translate a datasetfile into a double-matrix and then consolidate all double matrices into ONE double matrx.
Here my code:
folder_string = 'Diss_Data/Raw';
FolderContent = dir(folder_string);
No_ds = numel(FolderContent);
for i = 1:No_ds
if isdir(FolderContent(i).name)==0
file_string = FolderContent(i).name;
file_path = strcat(folder_string,'/',file_string)
dataset_filename = file_string(1:6);
load(file_path); %loads the suggested datasetfile; OKAY
M = double(dataset_filename);% returns an ASCII code number; WRONG; should transfer the datasetfile into a matrix M
vS = M(:,2:3);
%... to be continued
end
end

creating variables from structures in matlab

I have the following example which expresses the type of problem that I'm trying to solve:
clear all
textdata = {'DateTime','St','uSt','Ln','W'};
data = rand(365,4);
Final = struct('data',data,'textdata',{textdata})
clear textdata data
From this, Final.data contains values which correspond to the headings in Final.textdata excluding the first ('DateTime') thus Final.data(:,1) corresponds to the heading 'St'... and so on. What I'm trying to do is to create a variable in the workspace for each of these vectors. So, I would have a variable for St, uSt, Ln, and W in the workspace with the corresponding values given in Final.data.
How could this be done?
Will this solve your problem:
for ii=2:length( textdata )
assignin('base',Final.textdata{ii},Final.data(:,ii-1));
end
Let me know if I misunderstood.
The direct answer to your question is to use the assignin function, like so (edit: just like macduff suggested 10 minutes ago):
%Starting with a Final structure containing the data, like this
Final.textdata = {'DateTime','St','uSt','Ln','W'};
Final.data = rand(365,4);
for ix = 1:4
assignin('base',Final.textdata{ix+1}, Final.data(:,ix));
end
However, I strongly discourage using dynamic variable names to encode data like this. Code that starts this way usually ends up as spaghetti code full of long string concatenations and eval statements. Better is to use a structure, like this
for ix = 1:4
dataValues(Final.textdata{ix+1}) = Final.data(:,ix);
end
Or, to get the same result in a single line:
dataValues = cell2struct(num2cell(Final.data,1), Final.textdata(2:end),2)