# Creating a vectorized statement in MatLab to output a 5x5 Hilbert matrix

chopnhack
Homework Statement:
As an introduction to MatLab, we have been given various assignments to get familiar. Now on page nine I find myself getting an empty 1x0 vector instead of the anticipated 5x5 Hilbert matrix.
The problem is to create a 5x5 Hilbert matrix using vectorized statements only, no loops. (The loops I have already completed)
Relevant Equations:
Each element of the Hilbert matrix is defined by 1/(i+j-1). The solution should look like:

1.0000 0.5000 0.3333 0.2500 0.2000
0.5000 0.3333 0.2500 0.2000 0.1667
0.3333 0.2500 0.2000 0.1667 0.1429
0.2500 0.2000 0.1667 0.1429 0.1250
0.2000 0.1667 0.1429 0.1250 0.1111
My first attempt was:
V=zeros(5,5)
a=1;
i=1:5;
j=1:5;
V(i:j)=a./(i+j-1)

I figured to create a 5x5 with zeros and then to return and replace those values with updated values derived from the Hilbert equation as we move through i and j.
This failed with an error of : Unable to perform assignment because the left and right side have different number of elements.

My next attempt was:
i=1:5;
j=1:5;
V = 1:(1./(i+j-1)):0.111

I began my matrix at 1, just like the Hilbert example, use the Hilbert equation for the decrementer and the end point of the 5x5 is 0.111
This failed with an error of:

V =
1×0 empty double row vector

Can anyone provide some assistance?

Staff Emeritus
Homework Helper
Gold Member
It seems to me that you do not have a proper understanding about how the : operator works in Matlab or what certain other operations mean. Let us break it down.

My first attempt was:
V=zeros(5,5)
a=1;
i=1:5;
j=1:5;
V(i:j)=a./(i+j-1)
The four first rows do what you expect them to (although I do not understand why you pre-define a variable a). After those you will have both i and j equal to [1 2 3 4 5]. Now, the statement "i:j" in the argument does not do what you think it does. The purpose of the : operator is to create a vector with increments of 1 from i to j. It does so by just using the first element of either so the result of i:j is just a number 1 in this case. What you are writing in the fifth line is therefore:
V(1) = 1./(i+j-1)
Even though V is a matrix, you can always access its elements as enumerated vector elements, so the left-hand side actually has a meaning (in this case it is actually the element V(1,1)) and it is a single number, you are trying to assign the right-hand side to that single number. However, on the right hand side you have
1./(i+j-1)
Now, i+j is just vector addition so the result is i+j-1 = [1 3 5 7 9], which is not what you want to do. Upon taking 1./ this, you just do an element-wise division, resulting in [1 1/3 1/5 1/7 1/9]. This is a vector and you cannot assign a vector value to the single element V(1,1). This is what Matlab is telling you when it tells you the left and right have different numbers of elements.

V = 1:(1./(i+j-1)):0.111
Let us return to your use of the : operator. First of all, 1./(i+j-1) is equal to [1 1/3 1/5 1/7 1/9], just as above. This means that the : operator structure is equivalent to 1:1:0.111. You are therefore essentially telling Matlab that you want a vector starting at 1, with increments of 1, that has no elements larger than 0.111. This vector has zero elements.

In order to solve your issue, I suggest looking at creating matrices of the correct size that are valued according to row/column, call them I and J, and then work from there.

Homework Helper
Personally, I'd do this with REPMAT. I'll sketch that out in a minute, but first I want to help you understand the errors here a little more.

Code:
V=zeros(5,5)
a=1;
i=1:5;
j=1:5;
V(i:j)=a./(i+j-1)

i and j are both row vectors. That's what is created by the colon operator. So both of them are 1 x 5.
(i + j - 1) is going to be a row vector containing [1 2 3 4 5] + [1 2 3 4 5] - 1 = [2 4 6 8 10] - 1 = [1 3 5 7 9]. I'm pretty sure you didn't intend that.

(Side note: You probably noticed that you get lots of extraneous output here, for instance the contents of V after line 1. That may be useful for debugging, but otherwise you want to end your lines with semicolons.)

You don't need V(i:j) on the left since you're trying to create a 5 x 5 expression on the right. Just assign it to V.

So what you want is an expression that is 5 x 5. You aren't going to get that by adding a 1 x 5 to a 1 x 5. What in that expression told Matlab that you wanted one of those to be interpreted as a column?

So you should be thinking first of all in terms of the transpose operator ('). For instance i = (1:5)'; will make i the 5 x 1 column vector containing 1, 2, ..., 5.

This failed with an error of : Unable to perform assignment because the left and right side have different number of elements.
Because the right side is 1 x 5.

Code:
My next attempt was:
i=1:5;
j=1:5;
V = 1:(1./(i+j-1)):0.111

The colon operator is not vectorized.

OK, I said that I'd do it with REPMAT. The REPMAT makes a larger vector or matrix by replicating a smaller one. So (big hint) for instance if you create a 1 x 5 column vector and want to make a 5 x 5 matrix which has that in each column, you can do repmat(x, 1, 5); That is copying it 1 time in the vertical direction and 5 times in the horizontal direction.

Your first attempt was closer, but what you want to be manipulating are 5 x 5 matrices so that your result has the right shape and contains all the combinations.

So imagine the matrix expression 1./(I + J - 1) where I and J are 5 x 5 matrices constructed to give the right combination in each position. What's in those matrices? How do you construct them with REPMAT?

Homework Helper
Another very tricky and idiomatic solution would use MESHGRID. Just try typing [X, Y] = meshgrid(1:5, 1:5) without the semicolon so you see the result, and examine the output, and think about that in terms of your expression.

Staff Emeritus
Homework Helper
Gold Member
OK, I said that I'd do it with REPMAT.
I do not think this is the easiest way. Meshgrid is more suitable for this task.

Homework Helper
I do not think this is the easiest way. Meshgrid is more suitable for this task.

Which I saved for the followup reply, apparently typed while you were typing this As this appears to be a beginning Matlab class, I wasn't sure how tricky to get so was trying to go for more elementary operations.

Staff Emeritus
Homework Helper
Gold Member
Also, if you want to save typing, [I,J] = meshgrid(1:5) works fine. You could also use I = meshgrid(1:5,1:5) and replace J everywhere with I'. It will be equivalent.

chopnhack
Thank you gents!

I=1:5;
J=transpose(1:5);
V=1./(I+J-1)

I think I got it - by transposing one matrix, MATLAB implicitly extends zeros to create a 5x5 matrix before beginning the operation for V=. Then each value starting at 1,1 fills in the matrix, 1 then 0.5 across the first row,
etc.

Thanks!

Homework Helper
Don't have Matlab on this computer but I'd be very surprised if that worked. I is 1 x 5, J is 5 x 1 and so (I + J - 1) won't work.

matlab implicitly extends zeros to create a 5x5 matrix

No, I don't think Matlab would do that. As I said, I can't do the experiment right now.

chopnhack
Input:
I=1:5;
J=transpose(1:5);
V=1./(I+J-1)

output as copied from Matlab:
V = 5×5
1.0000 0.5000 0.3333 0.2500 0.2000
0.5000 0.3333 0.2500 0.2000 0.1667
0.3333 0.2500 0.2000 0.1667 0.1429
0.2500 0.2000 0.1667 0.1429 0.1250
0.2000 0.1667 0.1429 0.1250 0.1111