Assign many values of "solve" structure to matrix: MATLAB - matlab

I am trying to solve a large system of linear equations in matlab (about 3600 equations!) Since the number of variables is too many, I have to define them in a matrix. So I use this code to define the variables:
A = sym('A',[60,60]);
It has to be a 60x60 matrix because the variables correspond to a finite difference problem (i.e. a mesh grid).
After writing the corresponding equations in a for loop, I use the solve function in this way:
mysol = solve(eq,A);
Where eq is the equations matrix.
My problem is that, when I try to solve this system as shown in MATLAB help, i.e. writing something like this:
C(1,1) = mysol.A(1,1)
I get an error that says: "Reference to non-existent field 'A'". But if I write something like:
C(1,1) = mysol.A1_1
then it works.
Does anyone know how I can fix this? I don't want to do this for every variable!

You could try accessing the fields in the structure dynamically like so:
for ii = 1:60
for jj = 1:60
field = sprintf('A%d_%d', ii, jj);
C(ii, jj) = mysol.(field);
end
end

Related

Load an do operations with a matrix whose name varies within a Matlab loop

I have to run a Matlab loop indexed by x. At each iteration, I have to load and work with an array, A_x.mat, where the subscript x follows the loop index. How can I do that? Let me give you and example to highlight my issue. The example is very silly but serves my purposes.
X=10;
C=cell(X,1)
for x=1:X
load(['A_' num2str(x) '.mat']); %here I load A_x.mat
%C{x}=A_x*3;
end
I don't know how to compute A_x*3 in a way that allows the subscript x to vary. Could you advise?
To solve my issue I also tried
for x=1:X
B=load(['A_' num2str(x) '.mat']); %here I load A_x.mat and "rename" it B
%C{x}=B*3;
end
but B turns out to be a 1x1 struct with 1 field that is again A_x. Hence, I have not solved anything.
You can save the structure subfield name as a char and access the structure with it directly:
X=10;
C=cell(X,1)
for x=1:X
name = ['A_', num2str(x)];
data_structure = load([name, '.mat']); %here I load A_x.mat
C{x} = data_structure.(name) * 3;
end
Note that you could achieve something similar with eval() but that is not recommended. If ever you need to access variables dynamically like this, use a structure.

How to make a vector like vec(x) in MATLAB?

I am trying to replicate this formula:
I have gathered all variables in my workspace. However estimating vec(Theta') does not seem to work and so I am a little bit stuck.
Theta = A*B-C;
vTheta = vec(Theta');
A, B and C are defined. The problem is that MATLAB does not seem to know the function vec to do what I would like to do with Theta as in the formula.
How to fix this?
I don't know where you got that equation from, but vec is a function in R, maybe it's related to that? If you want to convert a matrix Theta into a vector, do
Theta(:)
Edit: If you need to transpose the matrix first, MATLAB might not let you do Theta'(:). Instead do it in two steps:
tmp = Theta'; tmp(:)
As written above the Colon Operator is the way vectorize defined variable.
Yet, sometime we want to vectorize a sub set of a variable.
Let's say we have a matrix - mA and we'd like to vectorize a sub section of it - mA(2:3, 4:7).
One way is to define a new variable and vectorize it:
vA = mA(2:3, 4:7);
vA = vA(:);
Yet, what if we only wanted to use this inside another expression and only once?
Could we escape the need to generate explicit variable?
Well, unfortunately MATLAB doesn't have the view() functionality like in Julia.
Yet if you want to avoid explicitly naming new variable (I'm not sure if MATLAB's JIT Engine can also void the memory allocation as Julia) you can do:
reshape(mA(2:3, 4:7), [], 1)
This will always yield a column vector.
You can also use:
reshape(mA(2:3, 4:7), 1, [])
To generate row vector.
For instance you can do:
reshape(mA(2:3, 4:7), 1, []) * reshape(mA(2:3, 4:7), [], 1, )
This will be the sum of squared values of those elements.

No output while using "gmres" in Matlab

I want to solve a system of linear equalities of the type Ax = b+u, where A and b are known. I used a function in MATLAB like this:
x = #(u) gmres(A,b+u);
Then I used fmincon, where a value for u is given to this expression and x is computed. For example
J = #(u) (x(u)' * x(u) - x^*)^2
and
[J^*,u] = fmincon(J,...);
withe the dots as matrices and vectors for the equalities and inequalities.
My problem is, that MATLAB delivers always an output with information about the command gmres. But I have no idea, how I can stop this (it makes the Program much slower).
I hope you know an answer.
Patsch
It's a little hidden in the documentation, but it does say
No messages are displayed if the flag output is specified.
So you need to call gmres with at least two outputs. You can do this by making a wrapper function
function x = gmresnomsg(varargin)
[x,~] = gmres(varargin{:});
end
and use that for your handle creation
x = #(u) gmresnomsg(A,b+u);

Function to find entries with same maximum value in a vector

In my project I need a function which returns the index of the largest element of a given vector. Just like max. For more than one entry with the same maximum value (which occurs frequently) the function should choose one randomly. Unlike max.
The function is a subfunction in a MATLAB Function Block in Simulink. And the whole Simulink model is compiled.
My basic idea was:
function ind = findOpt(vector)
index_max = find(vector == max(vector));
random = randi([1,length(index_max)],1);
ind = index_max(random);
end
But I got problems with the comparison in find and with randi.
I found out about safe comparison here: Problem using the find function in MATLAB. Also I found a way to replace randi([1,imax],1): Implement 'randi' using 'rand' in MATLAB.
My Code now looks like this:
function ind = findOpt(vector)
tolerance = 0.00001;
index_max = find(abs(vector - max(vector)) < tolerance);
random = ceil(length(index_max)*rand(1));
ind = index_max(random);
end
Still doesn't work. I understand that the length of index_max is unclear and causes problems. But I can not think of any way to know it before. Any ideas how to solve this?
Also, I'm shocked that ceil doesn't work when the code gets executed?? In debug mode there is no change to the input visible.
I thought about creating an array like: index_max = abs(vector - max(vector)) < tolerance; But not sure how that could help. Also, it doesn't solve my problem with the random selection.
Hopefully somebody has more ideas or at least could give me some hints!
I am using MATLAB R2012b (32bit) on a Windows7-64bit PC, with the Lcc-win32 C 2.4.1 compiler.
Edit:
Vector usually is of size 5x1 and contains values between -2000 and zero which are of type double, e.g. vector = [-1000 -1200 -1000 -1100 -1550]'. But I think such a simple function should work with any kind of input vector.
The call of length(index_max) causes an system error in MATLAB and forces me to shut it down. I guess this is due to the strange return I get from find. For a vector with all the same values the return from find is something like [1.000 2.000 1.000 2.000 0.000]' which doesn't make any sense to me at all.
function v= findOpt(v)
if isempty(v)
return;
end
v = find((max(v) - v) < 0.00001);
v = v(ceil(rand(1)*end));
end
I was indeed overloading, just like user664303 suggested! Since I can not use objects in my project, I wanted an function that behaves similar, so I wrote:
function varargout = table(mode, varargin)
persistent table;
if isempty(table) && ~strcmp(mode,'writeTable')
error(...)
end
switch mode
case 'getValue'
...
case 'writeTable'
table = ...
...
end
end
Wanted to avoid passing the dimensions for the table in every call and thought it would be enough if the first call initializes the Table with mode='writeTable'. Looks like this caused my problem.
No problems after changing to:
if isempty(table)
table = zeros(dim1,dim2,...)
end

Matlab integral function & function handles in a loop

'Outliers.m' is called from a higher level .m file. The variables are all defined in the higher level file, and set as globals for access by Outliers.m. The purpose of the code is to identify outliers using Chauvenets Criterion, and for this, I have to calculate the integral of the guassian distribution, using the Integral function and function handles. The code works and gives sensible values when I enter specific variables as a test, but I cannot get it to work in a loop. My data set is comprised of 7 individual samples, each 1x30, all of which need to be analyzed. I have had various errors, read through the guidance on Integral and function handles, but cannot seem to find the solution...Any help or guidance would be very much appreciated.... Here is my code:
n = 7
for x = 1:n
for y = 1:30
z(x,y) = abs((cc(x,y) - mastercc(1,y))/masterccstd(1,y));
xmax(x,y) = mastercc(1,y)+z(x,y)*masterccstd(1,y);
xmin(x,y) = mastercc(1,y)-z(x,y)*masterccstd(1,y);
p(x,y) = 1/(masterccstd(1,y)*(sqrt(2*pi)));
fun(x,y)= #(x,y,z) (exp(-1/2)*z(x,y).^2);
q(x,y) = integral(fun(x,y),xmin(x,y),xmax(x,y),'ArrayValued',true);
pq(x,y) = p(x,y)*q(x,y); % probability
value(x,y) = n*(1/pq(x,y));
count(x,y) = logical(value(x,y) <0.5);
badbins(x)=sum(count(x,:));
end
end
It seems like your error is caused by an invald function definition.
If you try it like this it should work:
fun = #(x,y,z) (exp(-1/2)*z(x,y).^2)
Now it can be called like this for example:
fun(1,2,magic(4))
Solution to the loop problem, courtesy Andrei Bobrov via Matlab Central, link below:
http://www.mathworks.com/matlabcentral/answers/103958#comment_177000
NB: Please note the code is not complete for the purpose I explained in the problem description, but it does solve the Loop error.