This question already has answers here:
Divide two polynomials using MATLAB
(2 answers)
Closed 6 years ago.
I'm currently working on a Cyclic Code program for a class in MATLAB and I'm trying to figure out the best way to divide two polynomials, the generator P(X) and the user input, shifted by 3 (x^3 * D(X)) in order to get the Quotient Q(X) and Remainder C(X), which would allow me to get the transmitted data T(X) = X^3*D(X) + C(X)
The code I have for my program so far takes in the users 4-bit input in binary, i.e.
Insert 4-bit input: 1001
Then it checks it to make sure its valid, and shifts it giving:
0 0 0 1 0 0 1
which stands for the polynomial
X^3 + X^6
I then need to divide that by the generator polynomial
P(X) = 1 + X + X^3
Working it out on paper,
x^6 + X^3
___________
x^3 + x + 1
Gives: Q(X) = X^3 + X
R(X) = X^2 + X
So, T(X) = X^6 + X^3 + X^2 + X, which is 0111001 for the Codeword
What would be the best way to do this?
I have tried the following:
% Prompt for User input
b4_in = input('Insert 4-bit input: ' ,'s'); %Input 1001
%% CHECK FOR VAILD INPUT %%
dec_in = bin2dec(b4_in)
bin_in = fliplr(de2bi(dec_in)) %User input in Binary
d = [0000000]; %Calculating X^3 * D(X)
d = bin_in;
d(7)=0;
d = fliplr(d); %Gives 0 0 0 1 0 0 1
d
gen_pol = [1 1 0 1] %P(X) = 1 + X + X^3
[q, c] = deconv(bin_in, gen_pol)
When I go this, I get:
q =
1
c =
0 -1 0 0
What do I need to do differently to get the following?
q = 0 1 0 1
c = 0 1 1
Thank you!
In MATLAB, polynomials read in a binary vector from left to right. For example, x^3+x is [1 0 1 0], x^2+x is [1 1 0]. The Quotient Q(X) should be x^3-x instead of x^3+x. Make sure your inputs are in the right format, and you should get the following result as expected,
q =
1 0 -1 0
c =
0 0 0 0 1 1 0
Related
I have the following function:
b = [-1 1];
m = b(randi(length(b),1,nsimul*n));
Is there a way to do sum to every n elements and store in another vector?
Example:
b = [-1 1];
m = b(randi(length(b),1,5*2));
m
m =
1 -1 1 -1 1 -1 -1 1 1 -1
A(1) = m(1) + m(2);
A(2) = m(3) + m(4);
A(3) = m(5) + m(6);
A(4) = m(7) + m(8);
A(5) = m(9) + m(10);
A
A =
0 0 0 0 0
you can use vec2mat to reshape you vector to a matrix of the dimension that fits the # of elements you want to sum on, and the you just need to sum the right dimension.
vec2mat is nice because it will pad with zeros the reminder of the 1D vector in case you choose a # of elements that is incommensurate with a NxM matrix, For example:
vec2mat(m,2)
ans =
1 -1
1 -1
1 -1
-1 1
1 -1
more generally, let's call n_elements the # of elements you want to sum on, then:
n_elements=2;
a=sum(vec2mat(m,n_elements),2)
But if the 1D vector and the # of elements is always commensurate and no padding is needed you can use the good old reshape, as mentioned in the comments below...
The following code snippet should provide what you are looking for:
% Define the parameters...
nsimul = 5;
n = 2;
b = [-1 1];
% Compute the final result...
m = b(randi(length(b),1,nsimul*n));
k = sum(reshape(m,n,[]).',2);
Given, for example, the vector:
m = [-1 -1 1 1 -1 -1 -1 1 1 1]
The final result s would be:
s = [-2 2 -2 0 2]
with the intermediate result k given by the reshape function equal to:
k = [
-1 -1
1 1
-1 -1
-1 1
1 1
]
Given this objective function:
Minimize:
f = (Ax + By)' * G * (Ax + By)
subject to some equalities and inequalities.
where x and y are real-valued vectors (decision variables) with p and q elements, respectively. A of size m * p, B of size m * q, G is a symmetric matrix of size m * m.
My question is how to write f in the form v' * G * v, such that it can be easily be used in quadprog. In other words, how to mix A, B and G?
This looks incompletely specified!
It seems, for whatever reason, you want to model in terms of two variable components. Now you did not specify how they interact with each other.
As most optimizers work on a single variable-vector, you need to concatenate yours.
As you did not show G, i'm assuming you got one G for x and one for y, let's call it H.
(Remark: not a matlab user; don't take example-syntax for granted!)
z = [x y]
P = blkdiag(G,H)
assuming x and y independent in regards to quadratic-term
e.g. no x0*y1 like terms
Solve: for z` P z
Example:
x = [x0 x1 x2]
y = [y0 y1]
G = [6 2 1; 2 5 2; 1 2 4]
H = [8 2; 2 10]
# G
6 2 1
2 5 2
1 2 4
# H
8 2
2 8
z = [x0 x1 x2 y0 y1]
P = [6 2 1 0 0; 2 5 2 0 0; 1 2 4 0 0; 0 0 0 8 2; 0 0 0 2 8]
# P
6 2 1 0 0
2 5 2 0 0
1 2 4 0 0
0 0 0 8 2
0 0 0 2 8
I am trying to use the convhull function in a loop and for that I need to split matrices into submatrices of different sizes. Here is the code I am using:
x1=data(:,5); % x centre location
y1=data(:,16); % y centre location
z1=phi*90; % phi angle value
n=300;
%Create regular grid across data space
[X,Y] = meshgrid(linspace(min(x1),max(x1),n), linspace(min(y1),max(y1),n));
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% PLOT USING SCATTER - TRYING TO ISOLATE SOME REGIONS %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
c=z1>10 & z1 < 20;
c=c.*1;
j=1;
for i=1:length(z1)
if z1(i)< 20 && z1(i)> 10
c(i) = 1;
else
c(i)= 0;
end
end
C=[c c c];
C = ~C;
elementalLengthA = cellfun('length',regexp(sprintf('%i',all(C,2)),'1+','match'));
elementalStartA = regexp(sprintf('%i',all(C,2)),'1+','start');
result = cell(length(elementalLengthA),1);
for i = 1:length(elementalLengthA)
result(i) = {C(elementalStartA(i):elementalStartA(i)+elementalLengthA(i)-1,:)};
length(x1(i))=length(cell2mat(result(i)));
length(y1(i))=length(cell2mat(result(i)));
end
My for loop doens't work properly and I get this error: ??? Subscript indices must either be real positive integers or
logicals.
My matrix C is an nx3 matrix made of lines of 1 and 0. With the result(i) line I am splitting the C matrix into submatrices of 1. Let's say
c = [1 1 1;
0 0 0;
0 0 0;
1 1 1;
1 1 1;
1 1 1;
0 0 0;
1 1 1;
1 1 1;]
Then
>> cell2mat(result(1))
ans =
1 1 1
>> cell2mat(result(2))
ans =
1 1 1
1 1 1
1 1 1
>> cell2mat(result(3))
ans =
1 1 1
1 1 1
Now x1 and y1 are two vector column nx1. And I want to split them according to the length of C submatrices. so length(x1(1)) should be 1, length(x1(2))=3, length(x1(3))=2 and same for the y vector.
Is it possible to do that?
EDIT:
Just to make it more clear
For instance
x1 =
1
2
3
4
5
6
7
8
9
and
y1 =
2
4
6
8
10
12
14
16
18
I want to get this as an output:
x1(1)=[1], x1(2)=[4 5 6]' and x1(3)=[8 9]'
y1(1)=[2], y1(2)[8 10 12]' and y1(3)=[16 18]'
Thanks
Dorian
I've the following code in C:
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
a[b[i]][c[j]]+=1;
}
}
Is there a way to write this in Matlab without using for loops? I mean the Matlab way using (:) which is faster.
Something like a(b(:),c(:))=a(b(:),c(:))+1 gives me out of memory error.
Interesting. While I don't (yet) have a solution for you (solution at bottom), I have a few notes and pointers:
1. The out of memory error is because you're creating a 512*256 by 512*256 element temporary matrix on the right hand side (a(b(:),c(:))+1). That is 2^34 bytes — 17GB! So that's why you're getting an out of memory error. Note, too, that this array isn't even what you want! Look at this example:
>> a = magic(5);
>> b = [1 5 4]; % The rows that contain the numbers 1,2,3 respectively
>> c = [3 4 5]; % The columns that contain ^ ...
Now, a(1,3) == 1, a(5,4) == 2, etc. But when you say a(b,c), you're selecting rows (1,5,4) and columns (3,4,5) for every one of those rows!
>> a(b,c)
ans =
1 8 15
25 2 9
19 21 3
All you care about is the diagonal. The solution is to use sub2ind to convert your subscript pairs to a linear index.
>> a(sub2ind(size(a),b,c))
ans =
1 2 3
2. Your proposed solution doesn't do what you want it to, either. Since Matlab lacks an increment operator, you are simply incrementing all indices that exist in (b,c) by one. And no more. It'll take some creative thinking to vectorize this. Use a smaller array to see what's going on:
>> a = zeros(4,4);
>> b = ones(8,4);
>> c = ones(8,4);
>> a(b,c) = a(b,c) + 1;
>> a
a =
1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
Edit Here we go! Vectorized incrementation:
>> idxs = sub2ind(size(a),b(:),c(:)); % convert subscripts to linear indices
>> [unique_idxs,~,ic] = unique(idxs); % Get the unique indices and their locations
>> increment_counts = histc(ic,1:max(ic)); % Get the number of occurrences of each idx
>> a(unique_idxs) = a(unique_idxs) + increment_counts;
Assuming you have the following matrices:
a = zeros(256); % or initialized with other values
b = randi(256, [512 256]);
c = randi(256, [512 256]);
Here is an even faster vectorized solution:
a = a + sparse(b,c,1,size(a,1),size(a,2));
Here is another one:
a = a + accumarray([b(:) c(:)], 1, size(a));
Answer: Yes.
a(b, c) = a(b, c) + 1;
Example:
>> a = zeros(5);
>> b = [1,3];
>> c = [2,4,5];
>> a(b,c) = a(b,c) + 1;
>> a
a =
0 1 0 1 1
0 0 0 0 0
0 1 0 1 1
0 0 0 0 0
0 0 0 0 0
I have the following equation:
((a^3)-(4*a^2))+[1 0 2;-1 4 6;-1 1 1] = 0
How do I solve this in MATLAB?
Here is one possibility:
% A^3 - 4*A^2 + [1 0 2;-1 4 6;-1 1 1] = 0
% 1) Change base to diagonalize the constant term
M = [1 0 2;-1 4 6;-1 1 1];
[V, L] = eig(M);
% 2) Solve three equations "on the diagonal", i.e. find a root of
% x^4 - 4*x^3 + eigenvalue = 0 for each eigenvalue of M
% (in this example, for each eigenvalue I choose the 3rd root,
% which happens to be real)
roots1 = roots([1 -4 0 L(1,1)]); r1 = roots1(3);
roots2 = roots([1 -4 0 L(2,2)]); r2 = roots2(3);
roots3 = roots([1 -4 0 L(3,3)]); r3 = roots3(3);
% 3) Build matrix solution and transform with inverse change of base
SD = diag([r1, r2, r3]);
A = V*SD*inv(V) % This is your solution
% The error should be practically zero
error = A^3 - 4*A^2 + [1 0 2;-1 4 6;-1 1 1]
norm(error)
(The error is actually of the order of 10^-14.)