I have an ODE that uses many functions. I wish to export these "helper" functions so that I may graph them vs the independent variable of the ODE.
function dFfuncvecdW = ODE(W,Ffuncvec);
X = Ffuncvec(1);
y = Ffuncvec(2);
#lots of code
R = ... #R is a function of X,W and y.
#and a few other functions that are a function of X,W and y.
dXdW = ... #some formula
dydW = ... #some formula
dFfuncvecdW = [dXdW; dydW];
end
I call this function with:
Wspan = [0 8000.]
X0 = [0; 1.]
[W,X] = ode45(#ODE, Wspan, X0);
I can easily output X or W to an excel file:
xlswrite(filename,X,'Conversion','A1');
But I what I need is to save "R" and many other functions' values to an Excel file.
How do I do that?
I am still extremely new to Matlab. I usually use Polymath, but for this system of ODE's, Polymath cannot compute the answer within a reasonable amount of time.
EDIT1: The code I use was generated by Polymath. I used a basic version of my problem so that Polymath may excecute the program as it only gives the Matlab code once the Polymath code has succefully run. After the export, the complete set of equations were entered.
The easiest, and possibly fastest, way to handle this is to re-evaluate your functions after ode45 returns W and X. If the functions are vectorized it will be easy. Otherwise, just use a simple for loop that iterates from 1 to length(W).
Alternatively, you can use an output function to save your values on each iteration to a file, or a global, or, most efficiently, a sub-function (a.k.a. nested function) variable that shares scope with an outer function (see here, for example). See this answer of mine for an example of how to use an output function.
I found a rather quick and painless solution to my answer.
I merely appended a text file with code inside the ode function.
EDIT: I am unable to comment because I do have enough rep on this branch of SE.
My solution was add the following code:
fid = fopen('abc1.txt', 'at');
fprintf(fid, '%f\n', T);
fclose(fid);
right above
dYfuncvecdW = [dFAdW; dFBdW; dFCdW; dFDdW; dydW];
at the end of the ode function. This proved to be a temporary solution. I have opened another question about the output I recieved.
Related
I am trying to produce the argument string for an anonymous function based on the number of input arguments without using for loops. For example, if N=3, then I want a string that reads
#(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3))
I tried using repmat('ax',1,N) but I cannot figure out how to interleave the (i) index.
Any ideas?
Aside: Great answers so far, the above problem has been solved. To provide some intuition for those who are wondering why I want to do this: I need to construct a very large matrix anonymous function (a Jacobian) on the order of 3000x3000. I initially used the Matlab operations jacobian and matlabFunction to construct the anonymous function; however, this was quite slow. Instead, since the closed form of the derivative was quite simple, I decided to form the anonymous function directly. This was done by forming the symbolic Jacobian matrix, J, then appending it to the above #() string by using char(J{:})' and using eval to form the final anonymous function. This may not be the most elegant solution but I find it runs much faster than the jacobian/matlabFunction combination, especially for large N (additionally the structure of the new approach allows for the evaluation to be done in parallel).
EDIT: Just for completeness, the correct form of the argument string for the anonymous function should read
#(ax1,ax2,ax3,ay1,ay2,ay3)
to avoid a syntax error associated with indexing.
I suggest the following:
N = 3;
argumentString = [repmat('ax(%i),',1,N),repmat('ay(%i),',1,N)];
functionString = sprintf(['#(',argumentString(1:end-1),')'], 1:N, 1:N)
First, you create input masks for sprintf (e.g. 'ax(%i)'), which you then fill in with the appropriate numbers to create the function string.
Note: the syntax #(ax(1),...) will not actually work. More likely, you want to use either #()someFunction(ax(1),...), or you are trying to pass multiple input arguments to an existing function, in which case storing the inputs in a cell array and calling the function as fun(axCell{:}) would work.
A solution would be to use arrayfun:
sx = strjoin(arrayfun(#(x) ['ax(' num2str(x) ')'], 1:3, 'UniformOutput', false), ',');
sy = strjoin(arrayfun(#(x) ['ay(' num2str(x) ')'], 1:3, 'UniformOutput', false), ',');
s = ['#(' sx ',' sy ')'];
contains
'#(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3))'
Best,
Try this:
N = 3;
sx = strcat('ax(', arrayfun(#num2str, 1:N, 'uniformoutput', 0), '),');
sy = strcat('ay(', arrayfun(#num2str, 1:N, 'uniformoutput', 0), '),');
str = [sx{:} sy{:}];
str = ['#(' str(1:end-1) ')']
I am interested in creating a list / array of functions "G" consisting of many small functions "g". This essentially should correspond to a series of functions 'evolving' in time.
Each "g" takes-in two variables and returns the product of these variables with an outside global variable indexed at the same time-step.
Assume obs_mat (T x 1) is a pre-defined global array, and t corresponds to the time-steps
G = []
for t in range(T):
# tried declaring obs here too.
def g(current_state, observation_noise):
obs = obs_mat[t]
return current_state * observation_noise * obs
G.append(g)
Unfortunately when I test the resultant functions, they do not seem to pick up on the difference in the obs time-varying constant i.e. (Got G[0](100,100) same as G[5](100,100)). I tried playing around with the scope of obs but without much luck. Would anyone be able to help guide me in the right direction?
This is a common "gotcha" to referencing variables from an outer scope when in an inner function. The outer variable is looked up when the inner function is run, not when the inner function is defined (so all versions of the function see the variable's last value). For each function to see a different value, you either need to make sure they're looking in separate namespaces, or you need to bind the value to a default parameter of the inner function.
Here's an approach that uses an extra namespace:
def make_func(x):
def func(a, b):
return a*b*x
return func
list_of_funcs = [make_func(i) for i in range(10)]
Each inner function func has access to the x parameter in the enclosing make_func function. Since they're all created by separate calls to make_func, they each see separate namespaces with different x values.
Here's the other approach that uses a default argument (with functions created by a lambda expression):
list_of_funcs = [lambda a, b, x=i: a*b*x for i in range(10)]
In this version, the i variable from the list comprehension is bound to the default value of the x parameter in the lambda expression. This binding means that the functions wont care about the value of i changing later on. The downside to this solution is that any code that accidentally calls one of the functions with three arguments instead of two may work without an exception (perhaps with odd results).
The problem you are running into is one of scoping. Function bodies aren't evaluated until the fuction is actually called, so the functions you have there will use whatever is the current value of the variable within their scope at time of evaluation (which means they'll have the same t if you call them all after the for-loop has ended)
In order to see the value that you would like, you'd need to immediately call the function and save the result.
I'm not really sure why you're using an array of functions. Perhaps what you're trying to do is map a partial function across the time series, something like the following?
from functools import partial
def g(current_state, observation_noise, t):
obs = obs_mat[t]
return current_state * observation_noise * obs
g_maker = partial(g, current, observation)
results = list(map(g_maker, range(T)))
What's happening here is that partial creates a partially-applied function, which is merely waiting for its final value to be evaluated. That final value is dynamic (but the first two are fixed in this example), so mapping that partially-applied function over a range of values gets you answers for each value.
Honestly, this is a guess because it's hard to see what else you are trying to do with this data and it's hard to see what you're trying to achieve with the array of functions (and there are certainly other ways to do this).
The issue (assuming that your G.append call is mis-indented) is simply that the name t is mutated when you loop over the iterator returned by range(T). Since every function g you create stores returns the same name t, they wind up all returning the same value, T - 1. The fix is to de-reference the name (the simplest way to do this is by sending t into your function as a default value for an argument in g's argument list):
G = []
for t in range(T):
def g(current_state, observation_noise, t_kw=t):
obs = obs_mat[t_kw]
return current_state * observation_noise * obs
G.append(g)
This works because it creates another name that points at the value that t references during that iteration of the loop (you could still use t rather than t_kw and it would still just work because tg is bound to the value that tf is bound to - the value never changes, but tf is bound to another value on the next iteration, while tg still points at the "original" value.
Let's assume that I want to create 10 variables which would look like this:
x1 = 1;
x2 = 2;
x3 = 3;
x4 = 4;
.
.
xi = i;
This is a simplified version of what I'm intending to do. Basically I just want so save code lines by creating these variables in an automated way. Is there the possibility to construct a variable name in Matlab? The pattern in my example would be ["x", num2str(i)]. But I cant find a way to create a variable with that name.
You can do it with eval but you really should not
eval(['x', num2str(i), ' = ', num2str(i)]); %//Not recommended
Rather use a cell array:
x{i} = i
I also strongly advise using a cell array or a struct for such cases. I think it will even give you some performance boost.
If you really need to do so Dan told how to. But I would also like to point to the genvarname function. It will make sure your string is a valid variable name.
EDIT: genvarname is part of core matlab and not of the statistics toolbox
for k=1:10
assignin('base', ['x' num2str(k)], k)
end
Although it is long overdue, i justed wanted to add another answer.
the function genvarname is exactly for these cases
and if you use it with a tmp structure array you do not need the eval cmd
the example 4 from this link is how to do it http://www.mathworks.co.uk/help/matlab/ref/genvarname.html
for k = 1:5
t = clock;
pause(uint8(rand * 10));
v = genvarname('time_elapsed', who);
eval([v ' = etime(clock,t)'])
end
all the best
eyal
If anyone else is interested, the correct syntax from Dan's answer would be:
eval(['x', num2str(i), ' = ', num2str(i)]);
My question already contained the wrong syntax, so it's my fault.
I needed something like this since you cannot reference structs (or cell arrays I presume) from workspace in Simulink blocks if you want to be able to change them during the simulation.
Anyway, for me this worked best
assignin('base',['string' 'parts'],values);
I have a script something like the following:
for
(do something)
end
And also outputs that use data output from the loop (which change each time -- when the script is run):
A = 1
A = 1.5
Etc.
I am looking to store this output that changes each time into a matrix.
Is this feasible?
for number of iterations
(Call script)
end
Output to excel
The reason I want to store the data into a matrix is to be able to output all the answers (for several iterations) into Excel at once.
Edit:
To give a better picture of what my output looks like it is something like this
Output = [rand() rand() rand(); rand() rand() rand()];
then I use this to create a new variable:
var = Output(1,1)./Output(2,1);
each time I run the script the answer changes. This new answer each time, is what I am looking to save in a matrix. Hope that clears things up.
Depending on the type of output/outputs from each loop you can, trivially, save intermediate results in one out of many MATLAB data structures(randn is used in the following as a sample of "do something"):
nIterations = 10;
% scalar output
A = zeros(1, nIterations);
for n=1:nIterations
A(n) = randn;
end
% matrix ouput of possibly changing size
B = cell(1, nIterations);
for n=1:nIterations
B{n} = randn(1, n+1);
end
% matrix output of fixed size
C = zeros(3, 3, nIterations);
for n=1:nIterations
C(:,:,n) = randn(3, 3);
end
Assuming that var is the thing you want to put in the matrix after each iteration, I suggest the following:
Add another for loop around your code, for example loop over i, then in the end do not assign the value to var, but to var(i).
Depending on your output you need to choose the variable type of var, for example cell or matrix.
If I use the inline function in MATLAB I can create a single function name that could respond differently depending on previous choices:
if (someCondition)
p = inline('a - b','a','b');
else
p = inline('a + b','a','b');
end
c = p(1,2);
d = p(3,4);
But the inline functions I'm creating are becoming quite epic, so I'd like to change them to other types of functions (i.e. m-files, subfunctions, or nested functions).
Let's say I have m-files like Mercator.m, KavrayskiyVII.m, etc. (all taking a value for phi and lambda), and I'd like to assign the chosen function to p in the same way as I have above so that I can call it many times (with variable sized matrices and things that make using eval either impossible or a total mess).
I have a variable, type, that will be one of the names of the functions required (e.g. 'Mercator', 'KavrayskiyVII', etc.). I figure I need to make p into a pointer to the function named inside the type variable. Any ideas how I can do this?
Option #1:
Use the str2func function (assumes the string in type is the same as the name of the function):
p = str2func(type); % Create function handle using function name
c = p(phi, lambda); % Invoke function handle
NOTE: The documentation mentions these limitations:
Function handles created using str2func do not have access to variables outside of their local workspace or to nested functions. If your function handle contains these variables or functions, MATLABĀ® throws an error when you invoke the handle.
Option #2:
Use a SWITCH statement and function handles:
switch type
case 'Mercator'
p = #Mercator;
case 'KavrayskiyVII'
p = #KavrayskiyVII;
... % Add other cases as needed
end
c = p(phi, lambda); % Invoke function handle
Option #3:
Use EVAL and function handles (suggested by Andrew Janke):
p = eval(['#' type]); % Concatenate string name with '#' and evaluate
c = p(phi, lambda); % Invoke function handle
As Andrew points out, this avoids the limitations of str2func and the extra maintenance associated with a switch statement.