Problem with a variable not changing value in MATLAB - matlab

So I have one problem with my code, which is that one variable is not working as it's supposed to do. Here are the codes I'm using:
format long
f = inline('-x.^2');
for i = 0:10
[I(i+1) h(i+1) tid(i+1)] = trapets(f,0,1,2^i);
end
for i = 0:10
trunk(i+1) = I(i+1) - log(2);
end
hold on
grid on
plot(log(h),log(trunk),'r+')
t = -7:0;
c = polyfit(log(h),log(trunk),1);
yy = polyval(c,t);
plot(t,yy)
grid off
hold off
koefficienter = real(c)
and also this:
function [ I,h,tid ] = trapets(f,a,b,n )
h=(b-a)/n;
tic;
I=(f(a)+f(b));
for k=2:2:n-2
I = I+2*f(a+k*h);
end
for k = 1:2:n-1
I = I + 4*f(a+k*h);
end
I = I * h/3;
tid = toc;
end
So the problem here is that the variable I is not changing value. It gets 11 values when I run the first code (I don't run the last code I wrote, it's only used by the first one), but the values are all the same. I don't know if the problem is that the variable n, which I use in the the second code, never change value, although I'm trying to do that with the "2^i" part in "trapets(f,0,1,2^i)". If the case is that n never change value, is there a solution to do that?
And if the problem is not the variable n, why doesn't the variable I change value in the code?

After running your program I found out the I always equals -1/h after the for loops, which makes I = I * h/3; always give you the same result.

Related

Why does matlab warn to preallocate a variable which is getting reset every loop?

There is a cell variable in my program which Matlab warns to preallocate it. The simple form of code is sth like this:
for i = 1:2
a = [];
a = [a,{'abc'}];
end
First I want to know why a should be preallocated, since it's getting reset in each loop. Second I don't know how to preallocate it. When I try to do so, Matlab gives me another warning, saying "The variable appears to be preallocated, but preallocation is not recommended here".
I use this code before the loop:
a = cell(1,2);
To be more specific:
for i = 1:2
a = [];
if condition1
a = {'abc'};
end
if condition2
a = [a,{'def'}];
end
b = [{'string'},a];
end
I want b to be a 1x1 cell array if the conditions are not true, so I need to reset a to an empty var in each loop.
Update:
I found a way, hinted by Lee's answer, but still doesn't know why. Using a = [a(:),{'def'}]; instead of a = [a,{'def'}]; solved the warning.
You made a a new variable, thus the former a = cell(1,2) was never used, which made matlab raised the warning.
You can use sth like
a = cell(1,2);
for ii = 1:2
a{ii} = 'abc';
end
or if you really want to change the size of a,
for ii = 1:2
a = {'a1'};
a = [a(:); {'abc'}];
end

Looping a Function in Matlab

total newbie here. I'm having problems looping a function that I've created. I'm having some problems copying the code over but I'll give a general idea of it:
function[X]=Test(A,B,C,D)
other parts of the code
.
.
.
X = linsolve(K,L)
end
where K,L are other matrices I derived from the 4 variables A,B,C,D
The problem is whenever I execute the function Test(1,2,3,4), I can only get one answer out. I'm trying to loop this process for one variable, keep the other 3 variables constant.
For example, I want to get answers for A = 1:10, while B = 2, C = 3, D = 4
I've tried the following method and they did not work:
Function[X] = Test(A,B,C,D)
for A = 1:10
other parts of the code...
X=linsolve(K,L)
end
Whenever I keyed in the command Test(1,2,3,4), it only gave me the output of Test(10,2,3,4)
Then I read somewhere that you have to call the function from somewhere else, so I edited the Test function to be Function[X] = Test(B,C,D) and left A out where it can be assigned in another script eg:
global A
for A = 1:10
Test(A,2,3,4)
end
But this gives an error as well, as Test function requires A to be defined. As such I'm a little lost and can't seem to find any information on how can this be done. Would appreciate all the help I can get.
Cheers guys
I think this is what you're looking for:
A=1:10; B=2; C=3; D=4;
%Do pre-allocation for X according to the dimensions of your output
for iter = 1:length(A)
X(:,:,iter)= Test(A(iter),B,C,D);
end
X
where
function [X]=Test(A,B,C,D)
%other parts of the code
X = linsolve(K,L)
end
Try this:
function X = Test(A,B,C,D)
% allocate output (it is faster than changing the size in every loop)
X = {};
% loop for each position in A
for i = 1:numel(A);
%in the other parts you have to use A(i) instead of just A
... other parts of code
%overwrite the value in X at position i
X{i} = linsolve(K,L);
end
end
and run it with Test(1:10,2,3,4)
To answer what went wrong before:
When you loop with 'for A=1:10' you overwrite the A that was passed to the function (so the function will ignore the A that you passed it) and in each loop you overwrite the X calculated in the previous loop (that is why you can only see the answer for A=10).
The second try should work if you have created a file named Test.m with the function X = (A,B,C,D) as the first code in the file. Although the global assignment is unnecessary. In fact I would strongly recommend you not to use global variables as it gets very messy very fast.

How to get out a value outside of objective function of multistart (MS) of Matlab

I have a multi-start fmincon code. One variable needs to be determined: u0. Inside ObjectiveFunc there is a variable, Parameter I need to output when running multi-start, so I am trying to output a parameter that changes inside an objective function. I wrote a simple example below.
How can I output the value of the Parameter inside Func(u0) below when running run(ms,Prob,big start)?
ObjectiveFunc = #(u0) Func(u0);
gs = GlobalSearch; ms = MultiStart(gs); opts = optimoptions(#fmincon);
Prob = createOptimProblem('fmincon','x0',1,'objective',ObjectiveFunc,'options',opts);
u0_ini_range = 0.1:1:20;
[u0_iniGrid] = ndgrid(u0_ini_range);
W = u0_iniGrid(:);
bigstart = CustomStartPointSet(W);
[u0_OptVal Delta_u0] = run(ms,Prob,bigstart);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function Delta_u0 = Func(u0)
Parameter = randn(1);
Delta_u0 = u0+Parameter;
There are a variety of ways to solve this issue. None of them are pretty. The problem is confounded due to the use of MultiStart, which runs multiple instances simultaneously, only one of which returns the global optimum. This means that the last evaluation of your objective function (and it's call to randn) isn't necessarily the relevant one.
Here's one way to accomplish this with persistent variables. First, you objective function need to look something like this (here Delta is your Parameter):
function [z,Delta_u0_Opt]=HBM1_SlipSolution02hbm3Fcn(u0)
persistent Delta idx;
if isempty(idx)
idx = 0; % Initialize persistent index
end
if nargout > 1
% Output Delta history
Delta_u0_Opt = Delta;
z = (u0-Delta).^2;
else
% Normal operation
idx = idx+1;
Delta(idx) = randn; % Save Delta history
z = (u0-Delta(idx)).^2;
end
Then run your setup code as before:
ObjectiveFunc = #(u0)HBM1_SlipSolution02hbm3Fcn(u0);
u0_ini0 = 0;
gs = GlobalSearch;
ms = MultiStart(gs);
opts = optimoptions(#fmincon);
Lowbound = 0.1;
Xst_rig = 1;
Upbound = 20*Xst_rig;
Prob = createOptimProblem('fmincon','x0',u0_ini0,'objective',ObjectiveFunc,...
'lb',Lowbound,'options',opts);
u0_ini_range = 0.1:1:Upbound;
[u0_iniGrid] = ndgrid(u0_ini_range);
W = u0_iniGrid(:);
bigstart = CustomStartPointSet(W);
[u0_OptVal,fval1] = run(ms,Prob,big start);
Then extract your Delta value:
[fval2,Delta_u0_Opt] = HBM1_SlipSolution02hbm3Fcn(u0_OptVal)
Delta_u0_Opt = Delta_u0_Opt(fval1==fval2)
The main problem with this solution is that the entire history of Delta must be retained via constantly appending to a vector. And it requires that the function value of the solution, fval1, uniquely match only one of fval2. The solution could probably be optimized a bit and the last issue resolved by saving more state history and clever use of an output function. I have no idea how or if this would work if you decide to turn on UseParallel. As you can see, this optimization scheme is not at all designed for what you're trying to get it to do.
Finally, are you sure that it's a good idea to use random values in the way that you are for this kind of optimization scheme? At minimum, be sure to specify a seed so results can be replicated. You might consider creating your own global optimization method based on fmincon if you want something more straightforward and efficient.

How to update a uitable after creation from other functions?

I created a matfile in which I store data that are constantly overwritten by user behavior. This occurs in a function "test()".
n=1
while n < 5
myVal = double(Test704(1, 780, -1)) %Returns the user's behavior
if myVal == 1
n = n + 1 %"n" is the overwritten variable in the matfile
end
save('testSave1.mat') %The matfile
m = matfile('testSave1.mat')
end
Then, I want to display these data in another function (it is essential to have two separated functions) called "storageTest()". More particularly, storageTest() is a GUI function where I developped an uitable "t". So, I first call the function "test()" and give its output values as data of "t". Here is the code of the interesting part of "storageTest":
m = test()
d = [m.n]
t = uitable('Data',d, ...
'ColumnWidth',{50}, ...
'Position',[100 100 461 146]);
t.Position(3) = t.Extent(3);
t.Position(4) = t.Extent(4);
drawnow
This code executes only when "m = test()" running is over and displays me a tab in which I can see the final value of "n". However, I want my table to be displayed before and to see my value incrementing according to user's behavior.
I have searched on the web to solve my issue, but I cannot find any answer, is it possible to do such a thing?
Assuming I'm interpreting the question correctly, it should be fairly trivial to accomplish this if you initialize your table prior to calling test and then pass the handle to your table for test to update in the while loop:
For example:
function testGUI
% Initialize table
t = uitable('ColumnWidth',{50}, 'Position',[100 100 461 146]);
test(t)
function test(t)
n = 1;
while n < 5
n = n + 1;
t.Data = n;
pause(0.25); % Since we're just incrementing a number, a slight so we can actually see the change
end
When you run the above, you'll notice the data in your table iterating as expected.
excaza was a little faster in writing basically the same answer like me. As it looks a slightly different, I'll post it anyway.
function storagetest()
close all
f = figure;
data = [1];
t = uitable(f,'Data',data,'ColumnWidth',{50});
test()
end
function test()
% handle uitable
t = evalin('caller','t')
n = 1;
while n < 5
newVal = input('Enter a number:');
data = get(t,'Data');
set(t,'Data', [data; newVal]);
n = n + 1;
end
end
The "user behaviour" I imitated with the input function. The basic idea is to update your table from within test(). evalin you can use, if you don't want to pass parameters to test(), though passing the handle of the uitable directly is certainly the better option.
If you are working on a serious GUI project I highly recommend you reading this answer.

MATLAB: Nested for-loop takes longer every successive iteration

/edit: The loop doesn't become slower. I didn't take the time correctly. See Rasman's answer.
I'm looping over 3 parameters for a somewhat long and complicated function and I noticed two things that I don't understand:
The execution gets slower with each successive iteration, although the function only returns one struct (of which I only need one field) that I overwrite with each iteration.
The profiler shows that the end statement for the innermost for takes a quite long time.
Consider the following example (I'm aware that this can easily be vectorized, but as far as I understand the function I call can't):
function stuff = doSomething( x, y, z )
stuff.one = x+y+z;
stuff.two = x-y-z;
end
and how I execute the function
n = 50;
i = 0;
currenttoc = 0;
output = zeros(n^3,4);
tic
for x = 1:n
for y = 1:n
for z = 1:n
i = i + 1;
output(i,1) = x;
output(i,2) = y;
output(i,3) = z;
stuff = doSomething(x,y,z);
output(i,4) = stuff.one;
if mod(i,1e4) == 0 % only for demonstration, not in final script
currenttoc = toc - currenttoc;
fprintf(1,'time for last 10000 iterations: %f \n',currenttoc)
end
end
end
end
How can I speed this up? Why does every iteration take longer than the one before? I'm pretty sure this is horrible programming, sorry for that.
When I replace the call to doSomething with output(i,4)=toc;, and I plot diff(output(:,4)), I see that it's the call to fprintf that takes longer and longer every time, apparently.
Removing the if-clause returns to every iteration taking about the same amount of time.
So, the problem gets largely eliminated when I replace the if statement with:
if mod(i,1e4) == 0 % only for demonstration, not in final script
fprintf(1,'time for last 10000 iterations: %f \n',toc); tic;
end
I think the operation on toc may be causing the problem
It's MUCH faster if doSomething returns multiple output variables rather than a struct
function [out1,out2] = doSomething( x, y, z )
out1 = x+y+z;
out2 = x-y-z;
end
The fact that it gets slower on each subsequent iteration is strange and i have no explanation for it but hopefully that gives you some speed up at least.