matrix operators with element-wise calculations - matlab

If I have [1 2 3] and I need to respectively multiply it by [2 3 4] to make the array [1*2 2*3 3*4], how do I do that?
I can't seem to do [1 2 3]*[2 3 4] = [1*2 2*3 3*4]
My actual issue is:
At=sum(abs([1 2 3].*exp(i.*[4 5 6])))
Tried rewriting it with a bsxfun inside the sum, but I get an error about not enough elements. It works with [1x1] and [1x1], but I tried with [1x6000] and [1x6000] and AT is equal one value. Not sure if the sum there is a good idea.
How would I go about performing the above operation so that the 1 and 4 are affected together, the 2 and 5 are affected together, and the 3 and 6 are affected together such that 'At' gives a 3x1 or 1x3 array?
Thank you so much!
EDIT: Alright so it seems that the exponential function "works".
What doesn't work is that it either adds everything together or creates twice as many solutions as I need.
If I feed it this kind of info:
A1=[1 2]
A2=[1 2]
p=[0.1 0.2]
p=[0.1 0.2]
>> [At] = somme_signaux([A1 A2],[p1 p2]);
>> At
At = 1.0000 2.0000 1.0000 2.0000
I'm going to get 4 answers without the sum. I need 2 answers (the first and second answer added together (1+2), and the third and fourth answer added together(1+2)) into a 2 by 1 matrix.

I don't really get your issue? .* can be used for element-wise multiplication, i.e.
>> [1 2 3].*[2 3 4]
ans =
2 6 12
Also, the code with the complex exponential works for me.

Related

How can I find a row equal to a vector in a matrix in matlab ? In, particular I would like to have the indexes

I have a vector A=[1 2 3] and I have a matrix B=[5 6 8,1 2 3, 9 6 5]. How can I find the row indexes? I tried find but it didn't work
You can use the ismember function for a one-line solution to that question.
The usage will be like this:
[tf, index]=ismember(A,B,'rows');

Remove redundant points on plot

I trying to plot a function which has millions of points. Therefore it is not possible to plot the function as it would crash my computer. However, the entire plot consists of "elbows" in that more than 1 variable cannot change at a time.
Consider the following matrix
a = [1 2 3 4 4 4 4];
b = [1 1 1 1 2 3 4];
These points make the following figure when using plot(a,b)
However, upon closer inspection, I can reduce my plot vectors down to
a = [1 4 4];
b = [1 1 4];
and get the same plot.
My question is: what is a vectorized way to automatically remove every redundant point. I could easily loop through and search for points to remove but this would be expensive. I have tried using combinations of diff and cumsum to do this to no avail. I only have straight lines and right angles in the plot so I do not have to worry about anything of the form ax+b
You can use a diff(diff(a))~=0, or equivalently diff(a, 2)~=0, to get a perhaps cleaner looking solution. This will work whether you plug a or b into the diff function.
mat = [true, diff(a, 2)~=0, true];
a(mat)
ans =
1 4 4
b(mat)
ans =
1 1 4
Guess I'll answer my own question in case anyone else needs this. Basically what I'm doing is doing the first diff on each matrix to see if the values are changing between each element. The second diff looks for a change. Because we're looking for elbows, we end up switching from true on the x-axis to true on the y-axis. This is the point we're looking for. Then we add on the ends. From there we only keep the true elements for our original matrix.
mat = [true diff(logical(diff(a))-logical(diff(b))) true];
a(mat)
[1 4 4]
b(mat)
[1 1 4]
I'm open to alternative suggestions as this is very hacky.

How to add two matrices and get rid of Nans

How can I add two matrices and keep only the numbers ignoring the NaN values?
for example:
A=[NaN 2 NaN];
B=[1 NaN 3];
I want some form of plus C=A+B such that:
C=[1 2 3]
You can achieve this without using any specific function call just by setting the NaNs to 0s and then performing the sum:
A(A~=A)=0
B(B~=B)=0
C=A+B
Edit: Another way of achieving this as #rayryeng suggested in the first comment is to use isnan:
A(isnan(A))=0
B(isnan(B))=0
C=A+B
You can use nansum (you need Statistics and Machine Learning Toolbox):
C = nansum([A;B])
and get:
C =
1 2 3
Alternatively, you can use sum with an excluding NaN flag:
C = sum([A;B],'omitnan')
And you will get the same result.

MatLAB help: shuffling a predefined vector without consecutively repeating numbers (with equal occurrences of all values)

I'm having troubles with randomly shuffling a vector without repeating numbers (ex. 1 1 is not acceptable but 1 2 is acceptable), given that each value is repeated equally.
More specifically, I would like to repeat the matrix [1:4] ten times (40 elements in total) so that 1, 2, 3 and 4 would all repeat 10 times without being consecutive.
If there is any clarification needed please let me know, I hope this question was clear.
This is what I have so far:
cond_order = repmat([1:4],10,1); %make matrix
cond_order = cond_order(:); %make sequence
I know randperm is quite relevant but I'm not sure how to use it with the one condition of non-repeating numbers.
EDIT: Thank you for all the responses.
I realize I was quite unclear. These are the examples I would like to reject [1 1 2 2 4 4 4...].
So it doesn't matter if [1 2 3 4] occurs in that order as long as individual values are not repeated. (so both [1 2 3 4 1 2 3 4...] and [4 3 1 2...] are acceptable)
Preferably I am looking for a shuffled vector meeting the criteria that
it is random
there are no consecutively repeating values (ex. 1 1 4 4)
all four values appear equal amount of times
Kind of working with the rejection sampling idea, just repeating with randperm until a sequence permutation is found that has no repeated values.
cond_order = repmat(1:4,10,1); %//make matrix
N = numel(cond_order); %//number of elements
sequence_found = false;
while ~sequence_found
candidate = cond_order(randperm(N));
if all(diff(candidate) ~= 0) %// check if no repeated values
sequence_found = true;
end
end
result = candidate;
The solution from mikkola got it methodically right, but I think there is a more efficient way:
He chose to sample based on equal quantities and check for the difference. I chose to do it the other way round and ended up with a solution requiering much less iterations.
n=4;
k=10;
d=42; %// random number to fail first check
while(~all(sum(bsxfun(#eq,d,(1:n).'),2)==k)) %' //Check all numbers to appear k times.
d=mod(cumsum([randi(n,1,1),randi(n-1,1,(n*k)-1)]),n)+1; %generate new random sample, enforcing a difference of at least 1.
end
A subtle but important distinction: does the author need an equal probability of picking any feasible sequence?
A number of people have mentioned answers of the form, "Let's use randperm and then rearrange the sequence so that it's feasible." That may not work. What will make this problem quite hard is if the author needs an equal chance of choosing any feasible sequence. Let me give an example to show the problem.
Imagine the set of numbers [1 2 2 3 4]. First lets enumerate the set of feasible sequences:
6 sequences beginning with 1: [1 2 3 2 4], [1 2 3 4 2], [1 2 4 2 3], [1 2 4 3 2], [1 3 2 4 2], [1 4 2 3 2].
Then there are 6 sequences beginning with [2 1]: [2 1 2 3 4], [2 1 2 4 3], [2 1 3 2 4], [2 1 3 4 2], [2 1 4 2 3], [2 1 4 3 2]. By symmetry, there are 18 sequences beginning with 2 (i.e. 6 of [2 1], 6 of [2 3], 6 of [2 4]).
By symmetry there are 6 sequences beginning with 3 and another 6 starting with 4.
Hence there are 6 * 3 + 18 = 36 possible sequences.
Sampling uniformly from feasible sequences, the probability the first number is 2 is 18/36 = 50 percent! BUT if you just went with a random permutation, the probability the first digit is 2 would be 40 percent! (i.e. 2/5 numbers in set are 2)
If equal probability of any feasible sequence is required, you want 50 percent of a 2 as the first number, but naive use of randperm and then rejiggering numbers at 2:end to make sequence feasible would give you a 40 percent probability of the first digit being two.
Note that rejection sampling would get the probabilities right as every feasible sequence would have an equal probability of being accepted. (Of course rejection sampling becomes very slow as probability of being accepted goes towards 0.)
Following some of the discussion on here, I think that there is a trade-off between performance and the theoretical requirements of the application.
If a completely uniform draw from the set of all valid permutations is required, then pure rejection sampling method will probably be required. The problem with this of course is that as the size of the problem is increased, the rejection rate will become very high. To demonstrate this, if we consider the base example in the question being n multiples of [1 2 3 4] then we can see the number of samples rejected for each valid draw as follows (note the log y axis):
My alternative method is to randomly sort the array, and then if duplicates are detected then the remaining elements will again be randomly sorted:
cond_order = repmat(1:4,10,1); %make matrix
cond_order = reshape(cond_order, numel(cond_order), 1);
cond_order = cond_order(randperm(numel(cond_order)));
i = 2;
while i < numel(cond_order)
if cond_order(i) ~= cond_order(i - 1)
i = i + 1;
else
tmp = cond_order(i:end);
cond_order(i:end) = tmp(randperm(numel(tmp)));
end
end
cond_order
Note that there is no guarantee that this will converge, but in the case where is becomes clear that it will not converge, we can just start again and it will still be better that re-computing the whole sequence.
This definitely meets the second two requirements of the question:
B) there are no consecutive values
C) all 4 values appear equal amount of times
The question is whether it meets the first 'Random' requirement.
If we take the simplest version of the problem, with the input of [1 2 3 4 1 2 3 4] then there are 864 valid permutations (empirically determined!). If we run both methods over 100,000 runs, then we would expect a Gaussian distribution around 115.7 draws per permutation.
As expected, the pure rejection sampling method gives this:
However, my algorithm does not:
There is clearly a bias towards certain samples.
In the end, it depends on the requirements. Both methods sample over the whole distribution so both fill the core requirements of the problem. I have not included performance comparisons, but for anything other than the simplest of cases, I am confident that my algorithm would be much faster. However, the distribution of the draws is not perfectly uniform. Whether it is good enough is dependent on the application and the size of the actual problem.

Compare two vectors in Matlab

I think, the question might have already been asked before. But I could not find proper answer in this forum.
Acutally, I have 2 vectors( of unequal length). I need to compare the 2 vectors. I can do it using a for loop. But it is taking a very long time.
Any obvious method which I may be missising ?
here is a small code snippet:
a=[ 1 2 3 4 5 6 7 8 1 2 3 4];
b=[ 2 3 4];
How can we compare a and b. Basically I need the index in vector a when comparison returns true.
Thanks
You can use strfind() for this (it works with doubles):
idx = strfind(a, b);
idx will contain the indices of all matches.