Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I want to get the content of a variable from its name as a string:
%suppose that I have structures variables in the workspace:
struct_1=struct('field1' ,"str",'field2',0:5)
struct_2=struct('field1' ,"str",'field2',0:10)
struct_3=struct('field1' ,"str",'field2',0:20)
%and I have an other variable like:
a=5
var2='hello'
%and I want to concatenate all these structures in the same structure
%So i wan to get their name.
%I don't know if there is an other way to get just the structure variables
structures=who(str*)
array=[]
for i=1:length(structures)
array=[array; structures(i). field2]; % here I get an error because the content of structures are string representing the variable name
end
%create the new struct
str='newstr_value'
struct_4=struct('field1',str, 'field2',array)
How to fix this error and is there any way to do this better ?
While I would still highly recommend going back to the point of origin of these dynamically named structures (shame 🔔🔔🔔 on the toolbox creator if this is actually the output...) and fixing this problem there, there is an approach that does not require the use of eval.
Similar to my approach for a tangentially related question, you can save the desired structures to a temporary *.mat file and take advantage of load's optional structure output to consolidate the data structures for access in a more robust programmatic matter.
For example:
struct_1=struct('field1' ,"str",'field2',0:5);
struct_2=struct('field1' ,"str",'field2',0:10);
struct_3=struct('field1' ,"str",'field2',0:20);
save('tmp.mat', '-regexp', '^struct_');
clear
oldworkspace = load('tmp.mat');
varnames = fieldnames(oldworkspace);
nvars = numel(varnames);
% Get original structure fields
% The subsequent steps assume that all input structs have the same fields
fields = fieldnames(oldworkspace.(varnames{1}));
nfields = numel(fields);
% Initialize output struct
for ii = 1:nfields
newstruct.(fields{ii}) = [];
end
newstruct(nvars) = newstruct;
for ii = 1:nvars
for jj = 1:nfields
newstruct(ii).(fields{jj}) = oldworkspace.(varnames{ii}).(fields{jj});
end
end
Gives us:
Yay.
Not sure if your situation absolutely requires dynamic calls of variables by their string names. eval can solve your problem. However, eval is slow. At times, it is unreliable. You can easily have conflicting code as you build various components of your project. And in my experience, there have always been alternatives to eval. In your case, Adriaan outlined an example in his comment.
Since you are only trying to interface with a third-party toolbox, if the number of variables you read is reasonable, you can do the followings with eval.
array=struct;
for i=1:length(structures)
eval(['array(',num2str(i),').field2=',structures{i},';'])
end
If you know all the structs are named struct_#, you can also do
array=struct;
num=3; % the number of outputs from your toolbox
for i=1:num
eval(['array(',num2str(i),').field2=struct_',num2str(i),'.field2;'])
end
Note that your field2 values are all arrays. You can't just create an array and expect each "cell" to carry another array value. Arrays, or rather matrices, in Matlab are a special data type. They only take numerical values. (Matrices are highly optimized in Matlab in various ways. That is why we use Matlab.)
Also note that when you set equality of fields of structs, the equality is by reference. There is no deep copy of the data. Modifying one will modify another. (Just beware of this but don't necessarily rely on it. Deciding when to deep copy things is one of the things we let Matlab handle.)
As well, be careful with the result from who. You need to be absolutely clear with what is in the local scope. Above is assuming your result from calling structures=who(str*) is correct for your application.
Related
I have a differential equation that's a function of around 30 constants. The differential equation is a system of (N^2+1) equations (where N is typically 4). Solving this system produces N^2+1 functions.
Often I want to see how the solution of the differential equation functionally depends on constants. For example, I might want to plot the maximum value of one of the output functions and see how that maximum changes for each solution of the differential equation as I linearly increase one of the input constants.
Is there a particularly clean method of doing this?
Right now I turn my differential-equation-solving script into a large function that returns an array of output functions. (Some of the inputs are vectors & matrices). For example:
for i = 1:N
[OutputArray1(i, :), OutputArray2(i, :), OutputArray3(i, :), OutputArray4(i, :), OutputArray5(i, :)] = DE_Simulation(Parameter1Array(i));
end
Here I loop through the function. The function solves a differential equation, and then returns the set of solution functions for that input parameter, and then each is appended as a row to a matrix.
There are a few issues I have with my method:
If I want to see the solution to the differential equation for a different parameter, I have to redefine the function so that it is an input of one of the thirty other parameters. For the sake of code readability, I cannot see myself explicitly writing all of the input parameters as individual inputs. (Although I've read that structures might be helpful here, but I'm not sure how that would be implemented.)
I typically get lost in parameter space and often have to update the same parameter across multiple scripts. I have a script that runs the differential-equation-solving function, and I have a second script that plots the set of simulated data. (And I will save the local variables to a file so that I can load them explicitly for plotting, but I often get lost figuring out which file is associated with what set of parameters). The remaining parameters that are not in the input of the function are inside the function itself. I've tried making the parameters global, but doing so drastically slows down the speed of my code. Additionally, some of the inputs are arrays I would like to plot and see before running the solver. (Some of the inputs are time-dependent boundary conditions, and I often want to see what they look like first.)
I'm trying to figure out a good method for me to keep track of everything. I'm trying to come up with a smart method of saving generated figures with a file tag that displays all the parameters associated with that figure. I can save such a file as a notepad file with a generic tagging-number that's listed in the title of the figure, but I feel like this is an awkward system. It's particularly awkward because it's not easy to see what's different about a long list of 30+ parameters.
Overall, I feel as though what I'm doing is fairly simple, yet I feel as though I don't have a good coding methodology and consequently end up wasting a lot of time saving almost-identical functions and scripts to solve fairly simple tasks.
It seems like what you really want here is something that deals with N-D arrays instead of splitting up the outputs.
If all of the OutputArray_ variables have the same number of rows, then the line
for i = 1:N
[OutputArray1(i, :), OutputArray2(i, :), OutputArray3(i, :), OutputArray4(i, :), OutputArray5(i, :)] = DE_Simulation(Parameter1Array(i));
end
seems to suggest that what you really want your function to return is an M x K array (where in this case, K = 5), and you want to pack that output into an M x K x N array. That is, it seems like you'd want to refactor your DE_Simulation to give you something like
for i = 1:N
OutputArray(:,:,i) = DE_Simulation(Parameter1Array(i));
end
If they aren't the same size, then a struct or a table is probably the best way to go, as you could assign to one element of the struct array per loop iteration or one row of the table per loop iteration (the table approach would assume that the size of the variables doesn't change from iteration to iteration).
If, for some reason, you really need to have these as separate outputs (and perhaps later as separate inputs), then what you probably want is a cell array. In that case you'd be able to deal with the variable number of inputs doing something like
for i = 1:N
[OutputArray{i, 1:K}] = DE_Simulation(Parameter1Array(i));
end
I hesitate to even write that, though, because this almost certainly seems like the wrong data structure for what you're trying to do.
I am going to use an algorithm in a for loop as an iteration loop. I know that some of the calculations can be done once and the their results can be used as necessary inputs for the algorithm in the for loop so in this way there is no need to calculate the same things in each iteration. To do so, I calculate them once and put them in a structure.
I use structure since I have many variables to be kept to be used in the for loop and their name and size are different. I put them in the structure with the same name for example:
out.A = A;
out.myvector = myvector;
out.s = s;
out.Hx_l = Hx_l;
and so on. some of them are matrices, some of them cubes or variables with a forth dimension and some of them are cells.
Is there any way to preallocate this kind of structure?
You could initialise the structure the following way:
out = struct('A',[],'myvector',[],'s',[],'Hx',[]);
When you assign the variables afterwards, the structure fields will be already created. Usually the contents are not initialised upfront. Quoting Loren:
How important is it to initialize the contents of the struct. Of
course it depends on your specifics, but since each field is its own
MATLAB array, there is not necessarily a need to initialize them all
up front. The key however is to try to not grow either the struct
itself or any of its contents incrementally.
I would like to find global minima using an objective function I defined.
The code I used is:
opts = optimoptions(#fmincon,'Algorithm','interior-point');
gs = GlobalSearch;
problem = createOptimProblem('fmincon','x0',a,'objective', #(s) obj(supdata,s),'options',opts);
[xg, fg, exitflag, output, solutions ]=run(gs, problem)
The problem is that supdata is for a specific firm, and I need to get the optimal result for each firm (there are thousands of them). I want to apply this code using a big data input (which I already have, in a cell array, with each cell being a specific firm), and the output xg fg... are also varies among firms.
I was hoping to use a loop inside the function obj, but people here suggested that I to change my function to use cellfun: see my original question. But I don't know how to incorporate it into globalsearch. It is more complicated than just calling the solver fmincon.
This question already has answers here:
Dynamic variables matlab
(2 answers)
Closed 8 years ago.
I was wondering how I can use a for loop to create multiple matrix when given a certain number.
Such as If 3 was given I would need three matricies called: C1, C2 and C3.
k = 3
for i = 1:K
C... = [ ]
end
Not sure how to implement this.
The first thing coming in mind is the eval function mentioned by Dennis Jaheruddin, and yes, it is bad practice. So does the documentation say:
Why Avoid the eval Function?
Although the eval function is very powerful and flexible, it not
always the best solution to a programming problem. Code that calls
eval is often less efficient and more difficult to read and debug than
code that uses other functions or language constructs. For example:
MATLAB® compiles code the first time you run it to enhance performance for future runs. However, because code in an eval
statement can change at run time, it is not compiled.
Code within an eval statement can unexpectedly create or assign to a variable already in the current workspace, overwriting existing
data.
Concatenating strings within an eval statement is often difficult to read. Other language constructs can simplify the syntax in your
code.
The "safer" alternative is the function assignin:
The following will do exactly what you want:
letter = 'C';
numbers = 1:3;
arrayfun(#(x) assignin('base',[letter num2str(x)],[]),numbers)
I know cases where you need to create variables likes this, but in most cases it is better and more convenient to use cell arrays or structs.
The trick is to use a cell array:
k=3
C=cell(k,1)
for t=1:k
C{t}= rand(t)
end
If each matrix is of equal size, you would probably just want a three dimensional matrix rather than a cell array.
You now have one cell array,but can access the matrices like this:
C{2} %Access the second matrix.
The use of eval is almost inevitable in this case:
k = 3;
for i = 1:k
eval(sprintf('C%d = [];', i));
end;
Mind you that generating variable names for data storage rather than indexing them (numerically -- see the solution of Dennis Jaheruddin based on cell arrays -- or creating a dynamic struct with named fields that store the data) is almost always a bad idea. Unless you do so to cope up with some weird scripts that you don't want to / cannot modify that need some variables already created in the global workspace.
I would like to ensure that the input arguments to a user-defined MATLAB function (contained in an m-file) are of a certain type. I understand that MATLAB automatically assigns data types to variables (to the liking of some and the dismay of others), but I would like to know if there is an option of "strict data typing" in MATLAB, or something of the sort, especially for input arguments for a user-defined function.
I found a helpful explanation of MATLAB's "fundamental classes" (data types) at these two webpages:
http://www.mathworks.com/help/matlab/matlab_prog/fundamental-matlab-classes.html
http://www.mathworks.com/help/matlab/data-types_data-types.html
However, I have been unable to find an answer to the question of strict data typing, particularly for function input arguments. I thought it would be a pretty basic question that already had been answered in numerous places, but after extensive searching I have not yet found a conclusive answer. For now, I have been manually checking the data type using the is[TYPE]() functions and displaying an error message if it does not comply, though this seems sloppy and I wish I could just get MATLAB to enforce it for me.
Below is an example of a function in which I would like to specify the input argument data type. It resides in a file called strict_data_type_test.m in MATLAB's current path. In this function, I would like to force the variable yes_or_no to be of MATLAB's logical data type. I know I can use the islogical() function to manually check, but my question is if it is possible to have MATLAB enforce it for me. I also know that any non-zero double evaluates to true and a zero evaluates to false, but I want to force the user to send a logical to make sure the wrong argument was not sent in by accident, for example. Here is the example function:
function y = strict_data_type_test( x, yes_or_no )
% manual data type check can go here, but manual check is not desirable
if (yes_or_no)
y = 2 .* x;
else
y = -5 .* x;
end
end
Adding the data type before the input argument variable name (like in most programming languages) treats the data type text as another variable name instead of a data type identifier. From that it would seem that strict data typing is not possible in MATLAB by any means, but maybe one of you many gurus knows a useful trick, feature, or syntax that I have not been able to find.
validateattributes might also work for you, if there is an appropriate attribute for your case. For example if you want to enforce that yes_or_no is a logical scalar, you could try:
validateattributes(yes_or_no,{'logical'},{'scalar'})
Otherwise maybe an attribute like 'nonempty'.
I've gotten some great responses so I can't pick just one as the "accepted answer", but to summarize what I've learned from you all so far:
No, MATLAB does not have built-in strict data typing for function input arguments
MATLAB compiles the code before running, so manual validation checking should not be very taxing on performance (the profiler can be used to assess this)
Many helpful methods of doing the manual validation checking exist, listed here in order of most relevant to least relevant for what I was trying to do:
inputParser class
validateattributes()
Error/exception handling (throw(), error(), assert(), etc.)
MATLAB's built-in state detection functions (a.k.a predicate functions)
I can look through some MathWorks-provided MATLAB functions (or Statistics toolbox functions) for ideas on how to validate input arguments by typing edit followed by the function name. Two suggested functions to look at are normpdf() (from the Statistics toolbox) and integral(). Some other functions I found helpful to look at are dot() and cross().
Other thoughts:
It would appear that the inputParser class was the overall concensus on the most professional way to validate input arguments. It was noted on a related (but not duplicate) stackoverflow post that the newer MathWorks functions tend to make use of this class, suggesting that it may be the best and most up-to-date choice.
Since the MathWorks-provided MATLAB functions do not appear to enforce strict input argument data typing, this further suggests that even if it was possible to do so, it may not be a recommended approach.
MATLAB seems to regard "error handling" and "exception handling" as two different concepts. For example, here are two links to MATLAB's Documentation Center that show how MathWorks considers "error handling" and "exception handling" differently: MathWorks Documentation Center article on Error Handling, MathWorks Documentation Center article on Exception Handling. A relevant StackOverflow post has been made on this topic and can be found here (link). I contacted MathWorks and added some new information about this topic to that post, so if you are interested you may read more by following that link.
Matlab provides an 'inputParser' which allows to check inputs. Besides this you can use assertions:
assert(islogical(yes_or_no),'logical input expected')
To ensure the correct number of input arguments, use narginchk.
btw: Take a look in some Matlab functions like edit integral and check how tmw deals with this.
You may find writing this sort of code tedious or worry that it degrades performance:
if ~islogical(yes_or_no) && ~isscalar(yes_or_no)
error('test:NotLogicalType','Second argument must be logical (Boolean).');
end
if yes_or_no
y = 2 .* x;
else
y = -5 .* x;
end
Recall, however, that Matlab compiles the code before running so even if you need to test many conditions it will be quite fast. Run the profiler to see.
Another option in some cases (maybe not your example) is to use a lazier method. This option lets your code run with whatever inputs were provided, but uses a try/catch block to trap any error:
try
if yes_or_no
y = 2 .* x;
else
y = -5 .* x;
end
catch me
...
error('test:NotLogicalType','Second argument must be logical (Boolean).');
% rethrow(me);
end
The code above would produce an error if yes_or_no was a cell array for example (it will still allow non-Boolean, non-scalar, etc. values for yes_or_no though, but Matlab is often overly permissive). You can then either generate a custom error message, detect, what kind of error was thrown and try something else, etc. Many of the functions in the Statistics toolbox use this approach (e.g., type edit normpdf in your command window) for better or worse.