Symmetric matrix, value into c++ vector - c++

I am trying to solve the following problem. Let's say I have a symmetric matrix with size n. I want to take all the "important values", and store them into a vector. Let me give an example to explain it better.
Let's say I have the following matrix A = [1, 2, 3 // 2, 5, 6 // 3, 6, 9]. I want to define vector of size n*(n+1)/2 such that:
V = [A(0,0), A(0,1), A(0,2), A(1,1), A(1,2), A(2,2) ]
I want to find a function that receives as input two integer i and j, and outputs the corresponding value of the matrix. The catch is that I do not want to access the matrix directly, instead I want to access the vector.
This is my reasoning so far. If I have an input with j < i, I just swap them since the matrix is symmetric. If I have that i == 0, the position in the array is just j. If that is not the case, I think I need to do something like this. (n is the dimension of the matrix, and position is the integer that I need when for the array.)
int position = 0;
for(int k = 0; k < i; k++){
position = position + (n-k);
}
position = position + j % i;
However, this code fails. I think I'm close to the solution but I am missing something. Any help?

The last j % i should be j - i.
In addition, the loop is essentially doing
position = n + (n - 1) + ... + (n - i + 1);
which can be simplified to
position = (n * 2 - i + 1) * i / 2;
So you can simply write
position = (n * 2 - i + 1) * i / 2 + j - i;
or
position = (n * 2 - i - 1) * i / 2 + j;

You can do simply this:
int myvector[matrix.size()];
int pos = 0;
for(int i = 0; i < matrix.size(); i++){
for(int j = 0; j < matrix.size(); j++){
if(j > i) myvector[pos++] = matrix[i][j];
else myvector[pos++] = matrix[j][i];
}
}

Related

C++: Transpose of Matrix, using SINGLE DIMENSION dynamic array to save elements

Dear Friends I am having problem to transpose a matrix. The transposed matrix has elements that are undefined. Not sure what is wrong. Thank you for your time!
entries[i] is the dynamic array storing the elements in the matrix. Elements are stored row by row, from left to right. i.e. in a 3X3 matrix, entries[2] is 3rd element on the 1st row, entries[3] is 1st element on the 2nd row
n is the number of rows of matrix
m is the number of columns of matrix
Matrix Matrix::Transpose() const {
double* temp;
temp = new double[n * m];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
temp[(j - 1) * m + i - 1] = entries[(i - 1) * m + j - 1];
}
Matrix Result(m, n, temp);
delete temp;
return Result;
}
When the original matrix is a square, all elements of the transposed matrix are defined. When the original matrix is 1x3, then the resulting transposed 3x1 matrix has undefined elements for the 2nd and 3rd elements. I.e. (1 1 3) after transposed returns (1 -3452346326236 -12351251515)
The Matrix Print out function is below. The error likely comes from here too.
void Matrix::Print() const
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
cout << setw(13) << entries[(i - 1) * m + j - 1];
cout << endl;
}
}
When the matrix is not square, the line
temp[(j - 1) * m + i - 1] = entries[(i - 1) * m + j - 1];
is not right. It needs to be:
temp[(j - 1) * n + i - 1] = entries[(i - 1) * m + j - 1];
// ^^ needs to be n, not m.
Think of the 2D analogue. You want to use:
temp[j][i] = entries[i][j];
entries is a n x m matrix. For it, the 2D indices [i][j] are translated as [i*m + j] for the 1D index.
temp is a m x n matrix. For it, the 2D indices [j][i] are translated as [j*n + i] for the 1D index.
Suggestion for improved readability
Instead of n and m, use num_rows, and num_columns. You will find your code a lot more readable.

C++: Matrix Gauss Elimination Does Not Work: Using SINGLE DIMENSION Array to store elements

my codes does not work for Gauss Elimination for Matrix. The core code is ok, but it seems to be missing some final touch which I honestly dont know. Would be great if someone can point out the mistake.
Basically when I input a square 3x3 Matrix filled with 3s, I get back (3, 3, 3, 0, -3, -3, 0, 0, 3) but it should be (3, 3, 3, 0, 0, 0, 0, 0, 0)
n is number of rows of matrix and m is number of columns.
All elements of matrix are stored in a SINGLE DIMENSION array called entries[i]
My code below for GaussElimination basically starts with placing the row with the largest first element on the top row. Then after that I just delete the elements right below the top elements.
Matrix Matrix::GaussElim() const {
double maxEle;
int maxRow;
for (int i = 1; i <= m; i++) {
maxEle = fabs(entries[i-1]);
maxRow = i;
for (int k = i+1; k <= m; k++) {
if (fabs(entries[(k - 1) * n + i - 1]) > maxEle) {
maxEle = entries[(k - 1) * n + i - 1];
maxRow = k;
}
}
for (int a = 1; a <= m; a++) {
swap(entries[(i - 1) * m + a - 1], entries[(maxRow - 1) * m + a - 1]);
}
for (int b = i + 1; b <= n; b++) {
double c = -(entries[(b - 1) * m + i - 1]) / entries[(i - 1) * m + i - 1];
for (int d = i; d <= n; d++) {
if (i == d) {
entries[(b - 1) * m + d - 1] = 0;
}
else {
entries[(b - 1) * m + d - 1] = c * entries[(i - 1) * m + d - 1];
}
}
}
}
Matrix Result(n, m, entries);
return Result;
}
For starters, I'd suggest to drop the habit of starting the loops at 1 instead of the more idiomatic 0, it would simplify all of the formulas.
That said, this statement
else {
entries[(b - 1) * m + d - 1] = c * entries[(i - 1) * m + d - 1];
// ^^^
}
Looks suspicious. There should be a += (or a -=, depending on how you choose the sign of the pivot).
Another source of unexpected results is the way chosen to calculate the constant c:
double c = -(entries[(b - 1) * m + i - 1]) / entries[(i - 1) * m + i - 1];
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Even in case of partial pivoting, that value could be zero (or too small), due to the nature of the starting matrix, like in the posted example, or to numerical errors. In those cases, it would be preferable to just zero out all the remaining elements of the matrix.

How to turn equation with decrementing indexing into math equation with summation?

Similar to this question: Turn while loop into math equation?, I have the following nested loop that I am trying to convert into a math equation as I need to write this up in a format that doesn't look like code. I believe I am going to need some type of summation equation.
Here is the code:
int num = 0;
for (int i = nr - 1; i >= 0; i--) {
for (int j = nc - 1; j >= 0; j--) {
ela[i][j] = num;
eha[i][j] = num + ea[i][j] - 1;
num += ea[i][j];
}
}
I know that summations start from a lower bound and continue to a higher bound, so I'm not quite sure how to apply a summation here since I start from a higher index and continue to a lower index.
I'm not sure why I'm getting downvoted, as the question I referenced is very similar to mine, has the same tags and is upvoted 14 times. Please comment below if I can improve my question somehow.
Update:
I was able to update the formula as follows:
nr = 50;
nc = 10;
num = sum[ea[i,j],i=0,nr-1,j=0,nc-1]; // correct based upon nr, nc and ea
for (int i = 0; i < nr; i) {
for (int j = 0; j < nc; j++) {
num = num - ea[i,j];
ela[i][j] = num;
eha[i][j] = num + ea[i,j] - 1;
}
}
If I am right, you can transcribe the effect as
You can describe this as the matrix ela being a 2D suffix sum of the matrix ea (for every element, sum of the elements that follow in the lexicographical ordering), while eha is the sum of matrices ela and ea minus all ones.
If the problem is just with how to express the sum when you're looping the other direction, you can change your code to:
int num = 0;
for (int i = 0; i < nr; i++) {
for (int j = 0; j < nc; j++) {
ela[nr - i][nc - j] = num;
eha[nr - i][nc - i] = num + ea[nr - i][nc - j] - 1;
num += ea[nr - i][nc - j];
}
}
I'm not saying you have to change your code to this, but from here it should be more obvious how to change this to use summation notation.
It's hard to tell without any context, but the code in question becomes more intelligible if you think of the arrays as vectors enumerating the elements in reverse order, row-major. The code below is functionally equivalent to the original one posted, but arguably easier to follow.
// n.b. ela[nr - 1 - i][nc - 1 - j] == rela(nc * i + j);
int &rela(int k) { return ela[nr - 1 - k / nc][nc - 1 - k % nc]; }
int &reha(int k) { return elh[nr - 1 - k / nc][nc - 1 - k % nc]; }
int &rea(int k) { return ea[nr - 1 - k / nc][nc - 1 - k % nc]; }
for (int k = 0, sum = 0; k < nr * nc - 1; k++) {
rela(k) = sum;
sum += rea(k);
reha(k) = sum - 1;
}
In plain English, rela(k) is the partial sum of rea elements 0 ... k-1 and reha(k) is one less than the partial sum of rea elements 0 ... k (also, rela(k) == reha(k - 1) + 1 for k > 0).
Technically, this description could be translated back in terms of the 2d arrays, but it becomes rather messy quickly.

Divide array integer 2 even sums

I am finding hard to solve this programming problem. I am required to take an array of integers that can be of size N, anywhere from 2 <= N <= 30. I need to divide the array into two smaller arrays whose sums are equal, and if they are not equal, they need to be as close as possible to the same value. I would guess that using some sort of recursive function would be ideal in this situation, but if not, a dynamically programmed solution would work just as well.
I guess you can review wikipedia article on Partition problem. It provides a pseudocode of pseudopolynomial algorithm in c# which you can rather easily convert into c++:
public static bool BalancePartition(int[] S)
{
int n = S.Length;
int N = S.Sum();
bool[,] P = new bool[N / 2 + 1, n + 1];
for (int i = 0; i < n + 1; i++)
P[0, i] = true;
for (int i = 1; i <= N / 2; i++)
for (int j = 1; j <= n; j++)
if (S[j - 1] <= i)
P[i, j] = P[i, j - 1] || P[i - S[j - 1], j - 1];
else
P[i, j] = P[i, j - 1];
return P[N / 2, n];
}

matrix multiplication as column major

I am trying to multiply as column major and I can't seem to find the right formula!
I want to have the matrices as 1D.
Let's say I have these matrices:
A=
1 3
2 4
and B=
5 2 1
6 3 7
The above matrices are assumed that are stored already in column major order.
I am trying:
int main(int argc, const char* argv[]) {
int rows=2;
int cols=3;
int A[rows*rows];
int B[rows*cols];
int res[rows*cols];
A[0]=1;
A[1]=3;
A[2]=2;
A[3]=4;
B[0]=5;
B[1]=2;
B[2]=1;
B[3]=6;
B[4]=3;
B[5]=7;
/*A[0]=1;
A[1]=2;
A[2]=3;
A[3]=4;
B[0]=5;
B[1]=6;
B[2]=2;
B[3]=3;
B[4]=1;
B[5]=7;
*/
//multiplication as column major
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
res[i+j*rows]=0;
for (int k=0;k<rows;k++){
res[i+j*rows]+=A[i+k*rows]*B[k+j*cols];
}
}
}
for (int i=0;i<rows*cols;i++){
printf("\n\nB[%d]=%d\t",i,res[i]);
}
return 0;
}
I am not getting the correct results.
Also,I can't understand (in the case where the matrices are stored in column major already) ,how to index the matrices A and B.
A[0]=1;
A[1]=3;
...
or
A[0]=1;
A[1]=2;
...
I don't want to transpose the matrices and then use row major.
I want to handle the data as column major.
Because the indices ,if stored as column major,will be different (hence,will matter in order to do the multiplication).
There are two things that lead to your confusion here.
First, the data in your contiguous one-dimensional vector is not in column-major order as you say, but in row-major order, as is the usual layout of two-dimensional contiguous arrays in C. The linear one-dimensional indices of row i and column j in a matrix with M rows and N columns (MxN) are:
A[i*N + j] // row major
A[i + M*j] // column major
The "major" refers to the dimension of the outer loop when traversing the array sequentially with two nested loops:
n = 0;
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
printf("%8d", A[n++]);
}
printf("\n");
}
Second, you use the two dimensions rows and columns which are the dimensions of the resulting matrix, which is confusing, because the number of columns in A is rows.
In fact, there are three different dimensions involved in matrix multiplication when you multiply an MxL matrix A with an LxN matrix B to get an MxN matrix C. In your case, M and L happen to be both 2:
L (k) | N (j)
|
| 5 2 1
L (k) |
| 6 3 7
|
-----------------+-------------
|
1 3 | 23 11 22
M (i) |
2 4 | 34 16 30
|
The letters in parentheses are the variables the code below uses to iterate over the respective dimension.
Now you can multiply your matrices in row-major format:
#define M 2
#define N 3
#define L 2
int A[M * L] = {1, 3, 2, 4};
int B[L * N] = {5, 2, 1, 6, 3, 7};
int res[M * N];
int i, j, k;
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
res[j + i * N] = 0;
for (k = 0; k < L; k++) {
res[j + i * N] += A[k + i * L] * B[j + k * N];
}
}
}
for (i = 0; i < M * N; i++) printf("[%d] = %d\n", i, res[i]);
or in column-major format:
#define M 2
#define N 3
#define L 2
int A[M * L] = {1, 2, 3, 4};
int B[L * N] = {5, 6, 2, 3, 1, 7};
int res[M * N];
int i, j, k;
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
res[j * M + i] = 0;
for (k = 0; k < L; k++) {
res[j * M + i] += A[k * M + i] * B[j * L + k];
}
}
}
for (i = 0; i < M * N; i++) printf("[%d] = %d\n", i, res[i]);
Both input and output are in the respective matrix representation and differ in the two cases, of course.
What do you think about
res[i+j*rows]+=A[i+k*rows]*B[k+j*cols];
what it will do?
It will access array res, A and B out of bound when i and k becomes 1 and j becomes 2.
res[1+2*2]+=A[1+1*2]*B[1+2*3] = res[5]+=A[4]*B[7];
This will invoke undefined behavior and you may get either expected or unexpected result.
I think you need this:
res[i*rows+j] += A[i*rows + k] * B[j + k*cols];