Suppose x is an array [x1, x2, x3, x4, x5] and we want to merge x2 and x4. This is done by putting their sum in the array and removing x2 and x4 from the array. The output array should look like this: [x1, x2+x4, x3, x5].
Here is one way of doing this in Matlab:
tmp = x(2) + x(4);
x(2) = tmp;
x(4) = tmp;
[m,n] = unique(x,'first');
x(sort(n))
This method works as long as there are no duplicates in the array. Is there any clever Matlab way of doing this for any x without resorting to loops and shifting of array elements after merging values ?
If you want to transform this
x = [x(1) x(2) x(3) ... x(i)... x(j)... x(n)]
into this
x = [x(1) x(2) x(3) ... x(i)+x(j) ... **... x(n)]
where ** is empty and the new x is n-1 elements long, then you should do:
x(i) = x(i)+x(j);
x(j) = [];
no tmp, no sort nor unique.
Related
I'm starting to use functions handles in Matlab and I have a question,
what Matlab computes when I do:
y = (0:.1:1)';
fun = #(x) x(1) + x(2).^2 + exp(x(3)*y)
and what Matlab computes when I do:
fun = #(x) x + x.^2 + exp(x*y)
Because I'm evaluating the Jacobian of these functions (from this code ) and it gives different results. I don't understand the difference of putting x(i) or only x
Let's define a vector vec as vec = [1, 2, 3].
When you use this vec in your first function as results = fun(vec), the program will take only the particular elements of the vector, meaning x(1) = vec(1), x(2) = vec(2) and x(3) = vec(3). The whole expression then will look as
results = vec(1) + vec(2).^2 + exp(vec(3)*y)
or better
results = 1 + 2^2 + exp(3*y)
However, when you use your second expression as results = fun(vec), it will use the entire vector vec in all the cases like this
results = vec + vec.^2 + exp(vec*y)
or better
results = [1, 2, 3] + [1^2, 2^2, 3^2] + exp([1, 2, 3]*y)
You can also clearly see that in the first case, I don't really need to care about matrix dimensions, and the final dimensions of the results variable are the same as the dimensions of your y variable. This is not the case in the second example, because you multiply matrices vec and y, which (in this particular example) results in error, as the vec variable has dimensions 1x3 and the y variable 11x1.
If you want to investigate this, I recommend you split this up into subexpressions and debug, e.g.
f1 = #(x) x(1);
f2 = #(x) x(2).^2;
f3 = #(x) exp(x(3)*y);
f = #(x) f1(x) + f1(x) + f3(x)
You can split it up even further if any subexpression is unclear.
The distinction is that one is an array array multiplication (x * y, I'm assuming x is an array with 11 columns in order for the matrix multiplication to be consistent) and the other is a scalar array multiplication (x(3) * y). The subscript operator (n) for any matrix extracts the n-th value from that matrix. For a scalar, the index can only be 1. For a 1D array, it extracts the n-th element of the column/row vector. For a 2D array, its the n-th element when traversed columnwise.
Also, if you only require the first derivative, I suggest using complex-step differentiation. It provides reduced numerical error and is computationally efficient.
Interleaver: Assume we have vector X= randi(1,N) I would like to split the contents of X into two new vectors X1and X2 such that the first element of X is the first element of X1, the first element of X2 is the second element of X, the third element of X is the second element of X1 and the fourth element of X is the second element of X2... etc till the last element of the vector `X.
I have the following idea
X1(1)=X(1);
X2(1)=X(2);
for i=1:length(X)
X1(i)= X(i+2);
end
for j=2:length (X)
X2(i)= X(i+2)
end
My question is: is my method correct? is there a better way to do it?
Deinterleaver
I also have the reverse problem so basically in this case I have X1 and X2 and would like to recover X, how would I efficiently recover X?
I think the terminology in this question is reversed. Interleaving would be to merge two vectors alternating their values:
x1 = 10:10:100;
x2 = 1:1:10;
x = [x1;x2];
x = x(:).';
This is the same as the one-liner:
x = reshape([x1;x2],[],1).';
Deinterleaving would be to separate the interleaved data, as already suggested by David in a comment and Tom in an answer:
y1 = x(1:2:end);
y2 = x(2:2:end);
but can also be done in many other ways, for example inverting the process we followed above:
y = reshape(x,2,[]);
y1 = y(1,:);
y2 = y(2,:);
To verify:
isequal(x1,y1)
isequal(x2,y2)
I was hoping, as well for some cool new one liner, but anyway, following the previous answer you can use the same indexing expression for the assignment.
x = 1:20
x1 = x(1:2:end)
x2 = x(2:2:end)
y = zeros(20,1)
y(1:2:end) = x1
y(2:2:end) = x2
I think it's hard to get a cleaner solution than this:
x = 1:20
x1 = x(1:2:end)
x2 = x(2:2:end)
Just to add another option, you could use the deal function and some precomputed indices. This is basically the same as the answer from Peter M, but collecting the assignments into single lines:
X = randi(10, [1 20]); % Sample data
ind1 = 1:2:numel(X); % Indices for x1
ind2 = 2:2:numel(X); % Indices for x2
[x1, x2] = deal(X(ind1), X(ind2)); % Unweave (i.e. deinterleave)
[X(ind1), X(ind2)] = deal(x1, x2); % Interleave
I want to produce a plot with two y-axis and apply multiple datasets to one of the axis. For example
[hAx,hLine1,hLine2] = plotyy([x1',x2',x3'],[y1',y2',y3'],x4,y4);
where x1 and y1 are 1000x1-arrays, x2 and y2 are 2000x1-arrays and x3 and y3 are 3000x1-arrays. The range of the arrays is more or less the same. When i try producing this plot, MATLAB gets me an error saying
Error using horzcat Dimensions of matrices being concatenated are not
consistent.
Is there any workaround for this error?
EDIT:
Here's my real code, which is not working:
[hAx,hLine1,hLine2] = plotyy([erg_cm.Time.data,erg_cm.Time.data,t',t'],...
[erg_cm.Car_FxFL.data,erg_cm.Car_FxFR.data,Fx(1,:),Fx(2,:)],...
erg_cm.Time.data,diff);
And my original data:
erg_cm.Time.data is 1x4001
t is 80300x1
erg_cm.Car_FxFL.data is 1x4001
erg_cm.Car_FxFR.data is 1x4001
Fx is 4x80300
diff is 1x4001
Your x and y vectors are column vectors and you're trying to concatenate them horizontally, which you cannot do because they are not the same size. You want to vertically concatenate them:
[hAx,hLine1,hLine2] = plotyy([x1;x2;x3],[y1;y2;y3],x4,y4);
EDIT: This is what I'm testing with
erg_cm.Time.data = rand(1, 4001);
t = rand(80300, 1);
erg_cm.Car_FxFL.data = rand(1, 4001);
erg_cm.Car_FxFR.data = rand(1, 4001);
Fx = rand(4, 80300);
diff = rand(1, 4001);
[hAx,hLine1,hLine2] = plotyy([erg_cm.Time.data,erg_cm.Time.data,t',t'],...
[erg_cm.Car_FxFL.data,erg_cm.Car_FxFR.data,Fx(1,:),Fx(2,:)],...
erg_cm.Time.data,diff);
I've been trying to extend the xor-swap to more than two variables, say n variables. But I've gotten nowhere that's better than 3*(n-1).
For two integer variables x1 and x2 you can swap them like this:
swap(x1,x2) {
x1 = x1 ^ x2;
x2 = x1 ^ x2;
x1 = x1 ^ x2;
}
So, assume you have x1 ... xn with values v1 ... vn. Clearly you can "rotate" the values by successively applying swap:
swap(x1,x2);
swap(x2,x3);
swap(x3,x4);
...
swap(xm,xn); // with m = n-1
You will end up with x1 = v2, x2 = v3, ..., xn = v1.
Which costs n-1 swaps, each costing 3 xors, leaving us with (n-1)*3 xors.
Is a faster algorithm using xor and assignment only and no additional variables known?
As a partial result I tried a brute force search for N=3,4,5 and all of these agree with your formula.
Python code:
from collections import *
D=defaultdict(int) # Map from tuple of bitmasks to number of steps to get there
N=5
Q=deque()
Q.append( (tuple(1<<n for n in range(N)), 0) )
goal = (tuple(1<<( (n+1)%N ) for n in range(N)))
while Q:
masks,ops = Q.popleft()
if len(D)%10000==0:
print len(D),len(Q),ops
ops += 1
# Choose two to swap
for a in range(N):
for b in range(N):
if a==b:
continue
masks2 = list(masks)
masks2[a] = masks2[a]^masks2[b]
masks2 = tuple(masks2)
if masks2 in D:
continue
D[masks2] = ops
if masks2==goal:
print 'found goal in ',ops
raise ValueError
Q.append( (masks2,ops) )
I have a 4D array A size(l,k,s,r) and a cell array B size(i,j) where in each cell a different 4D array of coefficients size(l,k,s,r) is stored.
I want to make changes in the given array C of size(i,j) = C(i,j) + sum(sum(sum(sum(A.*B{i,j})))) without for loop.
in other words I need to extract one by one all arrays out of cell array B and multiply with A.
with the for loop i do it this way:
for i=1:length_of_first_dimension
for j=1:length_of_second_dimension
B_4D=B{i,j}; % extraction of 4D array
dummy(i,j)=sum(sum(sum(sum(B_4D.*A))));
end
end
C=C+dummy;
can anyone help me with that?
first, reshape B into a (length_of_first_dimension*length_of_second_dimension)-by-l*k*s*r 2D matrix
rB = cellfun( #(x) x(:).', B, 'uni', 0 ); %'
rB = vertcat(rB{:});
Now, reshape A into a l*k*s*r-by-1 column vector
rA = A(:);
And simply multiply them
rDummy = rB * rA; %// does the elem-wise product and summation quite quickly.
Reshape the result
dummy = reshape(rDummy, size(B) );
C = C + dummy;
As pointed by Divakar a more efficient way to reshape B would be
rB = reshape( cat( 5, B{:} ), numel(A), [] ).';
And a small benchmark can be found here.