To see the results of patternsearch optimization for each iteration in MATLAB - matlab

I have a optimization problem which is very time consuming and I need to do it many times (This is somehow a trial and error problem for me). However, I do not want to wait for the final result. I need to see the result of optimization at each iteration. More specifically, I want to see the x value (the solution) and am not so interested in fval (objective function value at x). Unfortunately, patternsearch only shows fval and not the solution of optimization at each iteration. I know that I should fix this problem through the "Output Function" and spent a lot of time and could not understand how to do it. To make everything convenient for you and let's consider the following simple optimization problem:
options = optimoptions('patternsearch');
options = optimoptions(options,'Display', 'iter','TolX',1e-6);
x0=2;lb=-3;ub=3;
x = patternsearch(#(x)x^2,x0,[],[],[],[],lb,ub,[],options);
The first few lines we see on the command window looks like the following:
Iter f-count f(x) MeshSize Method
0 1 4 1
1 2 4 0.5 Refine Mesh
2 3 0 1 Successful Poll
Unfortunately, I see nothing about x.
Would you please change my code so that I can also see the solution (x) at each iteration, it is greatly appreciated!
Babak

A valid output function handler for patternsearch should be specified as follows:
function [stop,options,optchanged] = fun(optimvalues,options,flag)
The following code should be enough to show the information you are looking for:
options = optimoptions('patternsearch');
options = optimoptions(options,'Display','iter','OutputFcns',#custom,'TolX',1e-6);
x0 = 2; lb = -3; ub = 3;
x = patternsearch(#(x)x^2,x0,[],[],[],[],lb,ub,[],options);
function [stop,options,optchanged] = custom(optimvalues,options,flag)
stop = false;
optchanged = false;
if (strcmp(flag,'iter'))
disp([' Iteration performed for X=' num2str(optimvalues.x)]);
end
end
Here is the output:
Iter Func-count f(x) MeshSize Method
0 1 4 1
Iteration performed for X=2
1 2 4 0.5 Refine Mesh
Iteration performed for X=0
2 3 0 1 Successful Poll
Iteration performed for X=0
3 3 0 0.5 Refine Mesh
Iteration performed for X=0
4 5 0 0.25 Refine Mesh
Iteration performed for X=0
...
It's just an example and you can, of course, tweak the function so that the text is displayed the way you prefer.

Related

How to efficiently apply correction to a time series with fully vectorized code in Matlab

I face a computation efficiency problem. I have a time series of a non-monotonically drifting variable, that is measurements of objects going through a machine (where the measurement is made) in a production line. The job to do consists of simulating what this time series would yield if there was a correction made to the object each time the measurement drifts above or below a threshold.
To do that I could simply make a for loop, and each time the thresholds are crossed, I apply the correction to the rest of the time series. However the time series is very long and the for loop take too much time to compute. I would like to vectorize this code to make it more efficient. Does anyone sees a way to do so?
Here is a working example using a for loop:
ts = [1 2 3 4 3 2 1 0 -1 -2 -3];
threshold = [-3.5 3];
correction = [1 -1];
for i = 1:numel(ts)
if ts(i) > threshold(2)
ts(i:end) = ts(i:end) + correction(2);
elseif ts(i) < threshold(1)
ts(i:end) = ts(i:end) + correction(1);
end
end
disp(ts)
The result is and should be the following array:
[1 2 3 3 2 1 0 -1 -2 -3 -3]
How can I vectorize this problem?

Build the matrix of all the combinations of given numbers using recursion [matlab]

Let say we have the vector v=[1,2,3] and we want to build the matrix of all the combinations of the numbers contained in v, i.e.
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Since I'm not good in recursion, firstly I tried to write the code to build such a matrix by using for loops
makeLoop([1,2,3])
function A = makeLoop(v)
loops=length(v);
for i = 1:loops
dummy=v;
m=factorial(loops)/loops;
A((1+m*(i-1)):m*i,1)=v(i);
v(i)=[];
loops2=length(v);
for j = 1:loops2
dummy2=v;
m2=factorial(loops2)/loops2;
A(((1+m2*(j-1))+m*(i-1)):(m2*j+m*(i-1)),2)=v(j);
v(j)=[];
loops3=length(v);
for k = 1:loops3
m3=factorial(loops3)/loops3;
A(((1+m2*(j-1))+m*(i-1)):(m2*j+m*(i-1)),3)=v(k);
end
v=dummy2;
end
v=dummy;
end
end
it seems like it work, but obviously write it all for a bigger v would be like hell. Anyway I don't understand how to properly write the recursion, I think the recursive structure will be something like this
function A = makeLoop(v)
if length(v)==1
"do the last for loop"
else
"do a regular loop and call makeLoop(v) (v shrink at each loop)"
end
but I don't get which parts should I remove from the original code, and which to keep.
You were very close! The overall structure that you proposed is sound and your loopy-code can be inserted into it with practically no changes:
function A = makeLoop(v)
% number of (remaining) elements in the vector
loops = length(v);
if loops==1 %"do the last for loop"
A = v; %Obviously, if you input only a single number, the output has to be that number
else %"do a regular loop and call makeLoop(v) (v shrink at each loop)"
%preallocate matrix to store results
A = zeros(factorial(loops),loops);
%number of results per vector element
m = factorial(loops)/loops;
for i = 1:loops
%For each element of the vector, call the function again with that element missing.
dummy = v;
dummy(i) = [];
AOut = makeLoop(dummy);
%Then add that element back to the beginning of the output and store it.
A((1+m*(i-1)):m*i,:) = [bsxfun(#times,v(i),ones(m,1)) AOut];
end
end
Explanation bsxfun() line:
First, read the bsxfun documentation, it explains how it works way better than I could. But long story short, with bsxfun() we can replicate a scalar easily by multiplying it with a column vector of ones. E.g. bsxfun(#times,5,[1;1;1]) will result in the vector [5;5;5]. Note that since Matlab 2016b, bsxfun(#times,5,[1;1;1]) can written shorter as 5.*[1;1;1]
To the task at hand, we want to add v(i) in front (as the first column) of all permutations that may occur after it. Therefore we need to replicate the v(i) into the 1. dimension to match the number of rows of AOut, which is done with bsxfun(#times,v(i),ones(m,1)). Then we just horizontally concatenate this with AOut.
You can simply use the perms function to achieve this:
v = [1 2 3];
perms(v)
ans =
3 2 1
3 1 2
2 3 1
2 1 3
1 3 2
1 2 3
If you want them sorted using the same criterion you applied in the desired output, use the following code (refer to this page for an official documentation of the sortrows functon):
v = [1 2 3];
p = perms(v);
p = sortrows(p)
p =
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

determine lag between two vector

I want to find the minimum amount of lag between two vector , I mean the minimum distance that something is repeated in vector based on another one
for example for
x=[0 0 1 2 2 2 0 0 0 0]
y=[1 2 2 2 0 0 1 2 2 2]
I want to obtain 4 for x to y and obtain 2 for y to x .
I found out a finddelay(x,y) function that works correctly only for x to y (it gives -4 for y to x).
is there any function that only give me lag based on going to the right direction of the vector? I will be so thankful if you'd mind helping me to get this result
I think this may be a potential bug in finddelay. Note this excerpt from the documentation (emphasis mine):
X and Y need not be exact delayed copies of each other, as finddelay(X,Y) returns an estimate of the delay via cross-correlation. However this estimated delay has a useful meaning only if there is sufficient correlation between delayed versions of X and Y. Also, if several delays are possible, as in the case of periodic signals, the delay with the smallest absolute value is returned. In the case that both a positive and a negative delay with the same absolute value are possible, the positive delay is returned.
This would seem to imply that finddelay(y, x) should return 2, when it actually returns -4.
EDIT:
This would appear to be an issue related to floating-point errors introduced by xcorr as I describe in my answer to this related question. If you type type finddelay into the Command Window, you can see that finddelay uses xcorr internally. Even when the inputs to xcorr are integer values, the results (which you would expect to be integer values as well) can end up having floating-point errors that cause them to be slightly larger or smaller than an integer value. This can then change the indices where maxima would be located. The solution is to round the output from xcorr when you know your inputs are all integer values.
A better implementation of finddelay for integer values might be something like this, which would actually return the delay with the smallest absolute value:
function delay = finddelay_int(x, y)
[d, lags] = xcorr(x, y);
d = round(d);
lags = -lags(d == max(d));
[~, index] = min(abs(lags));
delay = lags(index);
end
However, in your question you are asking for the positive delays to be returned, which won't necessarily be the smallest in absolute value. Here's a different implementation of finddelay that works correctly for integer values and gives preference to positive delays:
function delay = finddelay_pos(x, y)
[d, lags] = xcorr(x, y);
d = round(d);
lags = -lags(d == max(d));
index = (lags <= 0);
if all(index)
delay = lags(1);
else
delay = lags(find(index, 1)-1);
end
end
And here are the various results for your test case:
>> x = [0 0 1 2 2 2 0 0 0 0];
>> y = [1 2 2 2 0 0 1 2 2 2];
>> [finddelay(x, y) finddelay(y, x)] % The default behavior, which fails to find
% the delays with smallest absolute value
ans =
4 -4
>> [finddelay_int(x, y) finddelay_int(y, x)] % Correctly finds the delays with the
% smallest absolute value
ans =
-2 2
>> [finddelay_pos(x, y) finddelay_pos(y, x)] % Finds the smallest positive delays
ans =
4 2

Finding the greatest common divisor of a matrix in MATLAB

Im looking for a way to divide a certain matrix elements with its lowest common divisor.
for example, I have vectors
[0,0,0; 2,4,2;-2,0,8]
I can tell the lowest common divisor is 2, so the matrix after the division will be
[0,0,0;1,2,1;-1,0,4]
What is the built in method that can compute this?
Thanks in advance
p.s. I personally do not like using loops for this computation, it seems like there is built in computation that can perform matrix element division.
Since you don't like loops, how about recursive functions?
iif = #(varargin) varargin{2 * find([varargin{1:2:end}], 1, 'first')}();
gcdrec=#(v,gcdr) iif(length(v)==1,v, ...
v(1)==1,1, ...
length(v)==2,#()gcd(v(1),v(2)), ...
true,#()gcdr([gcd(v(1),v(2)),v(3:end)],gcdr));
mygcd=#(v)gcdrec(v(:)',gcdrec);
A=[0,0,0; 2,4,2;-2,0,8];
divisor=mygcd(A);
A=A/divisor;
The first function iif will define an inline conditional construct. This allows to define a recursive function, gcdrec, to find the greatest common divisor of your array. This iif works like this: it tests whether the first argument is true, if it is, then it returns the second argument. Otherwise it tests the third argument, and if that's true, then it returns the fourth, and so on. You need to protect recursive functions and sometimes other quantities appearing inside it with #(), otherwise you can get errors.
Using iif the recursive function gcdrec works like this:
if the input vector is a scalar, it returns it
else if the first component of the vector is 1, there's no chance to recover, so it returns 1 (allows quick return for large matrices)
else if the input vector is of length 2, it returns the greatest common divisor via gcd
else it calls itself with a shortened vector, in which the first two elements are substituted with their greatest common divisor.
The function mygcd is just a front-end for convenience.
Should be pretty fast, and I guess only the recursion depth could be a problem for very large problems. I did a quick timing check to compare with the looping version of #Adriaan, using A=randi(100,N,N)-50, with N=100, N=1000 and N=5000 and tic/toc.
N=100:
looping 0.008 seconds
recursive 0.002 seconds
N=1000:
looping 0.46 seconds
recursive 0.04 seconds
N=5000:
looping 11.8 seconds
recursive 0.6 seconds
Update: interesting thing is that the only reason that I didn't trip the recursion limit (which is by default 500) is that my data didn't have a common divisor. Setting a random matrix and doubling it will lead to hitting the recursion limit already for N=100. So for large matrices this won't work. Then again, for small matrices #Adriaan's solution is perfectly fine.
I also tried to rewrite it to half the input vector in each recursive step: this indeed solves the recursion limit problem, but it is very slow (2 seconds for N=100, 261 seconds for N=1000). There might be a middle ground somewhere, where the matrix size is large(ish) and the runtime's not that bad, but I haven't found it yet.
A = [0,0,0; 2,4,2;-2,0,8];
B = 1;
kk = max(abs(A(:))); % start at the end
while B~=0 && kk>=0
tmp = mod(A,kk);
B = sum(tmp(:));
kk = kk - 1;
end
kk = kk+1;
This is probably not the fastest way, but it will do for now. What I did here is initialise some counter, B, to store the sum of all elements in your matrix after taking the mod. the kk is just a counter which runs through integers. mod(A,kk) computes the modulus after division for each element in A. Thus, if all your elements are wholly divisible by 2, it will return a 0 for each element. sum(tmp(:)) then makes a single column out of the modulo-matrix, which is summed to obtain some number. If and only if that number is 0 there is a common divisor, since then all elements in A are wholly divisible by kk. As soon as that happens your loop stops and your common divisor is the number in kk. Since kk is decreased every count it is actually one value too low, thus one is added.
Note: I just edited the loop to run backwards since you are looking for the Greatest cd, not the Smallest cd. If you'd have a matrix like [4,8;16,8] it would stop at 2, not 4. Apologies for that, this works now, though both other solutions here are much faster.
Finally, dividing matrices can be done like this:
divided_matrix = A/kk;
Agreed, I don't like the loops either! Let's kill them -
unqA = unique(abs(A(A~=0))).'; %//'
col_extent = [2:max(unqA)]'; %//'
B = repmat(col_extent,1,numel(unqA));
B(bsxfun(#gt,col_extent,unqA)) = 0;
divisor = find(all(bsxfun(#times,bsxfun(#rem,unqA,B)==0,B),2),1,'first');
if isempty(divisor)
out = A;
else
out = A/divisor;
end
Sample runs
Case #1:
A =
0 0 0
2 4 2
-2 0 8
divisor =
2
out =
0 0 0
1 2 1
-1 0 4
Case #2:
A =
0 3 0
5 7 6
-5 0 21
divisor =
1
out =
0 3 0
5 7 6
-5 0 21
Here's another approach. Let A be your input array.
Get nonzero values of A and take their absolute value. Call the resulting vector B.
Test each number from 1 to max(B), and see if it divides all entries of B (that is, if the remainder of the division is zero).
Take the largest such number.
Code:
A = [0,0,0; 2,4,2;-2,0,8]; %// data
B = nonzeros(abs(A)); %// step 1
t = all(bsxfun(#mod, B, 1:max(B))==0, 1); %// step 2
result = find(t, 1, 'last'); %// step 3

Recursion in Matlab. why is my recursion not working past the first step?

So I am very new to Matlab and I have been tasked with implementing LU factorization. I have to do it recursively because we are not allowed to use for loops in our code, and recursion will give us optimal marks. I have written this code. The code works for the first step, and does what it is supposed to, but for the next two steps, the matrix is not modified at all. I have this code:
function[L, U] = myLU(A,B, pos)
%A = Mtrix that becomes U
%B = Matrix that becomes L
tmp_L = B;
[x,y] = size(A);
if pos > x
L = B;
U = A;
return
else
pos %<-- just to see if it iterates through everything
[tmp_U,tmp_L] = elimMat(A,pos);
myLU(tmp_U,tmp_L, pos+1);
end
L = tmp_L;
U = tmp_U;
end
I where elimMat(A, pos) returns the elimination matrix for column pos. as well as another matrix, which will end up being the matrix of multipliers. What i tried doing is then finding the LU factorization of this matrix A. since elimMat returns L and U(this works, if i do it manually it works), i had to make a function that allows me to do it automatically without using a for loop. I thought i would do it recursively. What i ended up doing is adding another variable B to the function so that i can store intermediate values of my matrix obtained in each step and put it all together later.
So here is my question. Am i implementing the recursion wrong? and if i am how can i fix it? The other thing i wanted to ask is how can i implement this so i do not need variable B as an additional imput, and only use the existing variables, or variables previously defined, to find the solution? I would really like only two inputs in my function: The matrix name and the starting index.
here is elimMat if if helps:
function [M,L] = elimMat(A,k)
%find the size of the matrix
[x,y] = size(A);
tmp_mat = zeros(x,y);
%M = The current matrix we are working on for Elimination -> going to
%become U.
%L = The L part of the matrix we are working on. Contains all the
%multipliers. This is going to be our L matrix.
for i = 1:x
mult = A(i,k)/A(k,k);
if i > k
tmp_mat(i,k) = mult;
P = A(k,:)*mult;
A(i,:) = A(i,:)-P;
elseif i == k
tmp_mat(k,k) = 1;
end
end
M = A;
L = tmp_mat;
end
thanks for any feedback you can provide.
Here is the output: WHAT I GET VS what it should be:
[U = VS [U =
1 2 2 1 2 2
0 -4 -6 0 -4 -6
0 -2 -4] 0 0 2
L = VS [L=
1 0 0 1 0 0
4 0 0 4 1 0
4 0 0] 4 0.5 1
As you can see only the first column is changed
You forgot to catch the output of your recursive call:
[tmp_L, tmp_U] = myLU(tmp_U,tmp_L, pos+1);
Matlab passes variables by value, so a function cannot change its input variable itself (ok, it can, but it's tricky and unsafe).
Your original version didn't return the updated matrices, so the outermost function call encountered the myLU() call, let the recursion unfold and finish, and then went on to use tmp_L and tmp_U as returned from the very first call to elimMAT(A,1).
Note that you might want to standardize your functions such that they return U and L in the same order to avoid confusion.