C++ - Can not access reverse indexing - c++

Please forgive me if the title is wrong, or, does not explain the problem correctly.
I'm trying to calculate the LU Decomposition of a matrix. Give the matrix M:
M = [1 2 3],
[1 2 3],
[3 3 0]
Now I'm following some code that was written here: Link
It uses j i in order to calculate the lower decomposition. When I try this approach, I keep getting a "Runtime error time: 0 memory: 3276 signal:11"
The thing that I do not understand is the fact that, when I output i, j inside of the 3x3 loop, I got:
i, j =
0 0 1 0 2 0
0 1 1 1 2 1
0 2 1 2 2 2
Then when output the indexes of j,i I get:
j, i =
0 0 0 1 0 2
1 0 1 1 1 2
2 0 2 1 2 2
Which seems right in terms of the order [0][0][0][2].........[2][2] so why can I not access this, inside my vector?
The code that I have written so far is:
void lu_decomposition(const std::vector<std::vector<double> > &vals)
{
std::vector<std::vector<double> > lower(3);
for(unsigned i=0; (i < 3); i++)
{
lower[i].resize(3);
for(unsigned j=0; (j < 3); j++)
{
if (j < i)
{
lower[j][i] = 0; // This is ok
}else{
lower[j][i] = vals[j][i]; // This is the runtime error
}
}
std::cout << std::endl;
}
}
The code is also visible on ideone

Let's concentrate on these lines:
lower[i].resize(3);
//...
lower[j][i] = vals[j][i];
Is the problem clear now? You're resizing lower[i], but then you're accessing lower[j] even for j > i, which has not been resized yet. If you need to access the matrix in this fashion, you'll have to preallocate it beforehand. That means to drop the resize call and instead initialise the variable like this:
std::vector<std::vector<double> > lower(3, std::vector<double>(3));

Related

How to resize 2d vector

#include <iostream>
#include <vector>
using namespace std;
int main(void)
{
vector<vector<int> > matrix;
matrix.resize(3, vector<int>(4, 1));
for (size_t i = 0; i < 3; i++)
{
for (size_t j = 0; j < 4; j++)
{
cout << matrix[i][j];
}
cout << endl;
}
matrix.resize(5, vector<int>(7, 0));
for (size_t i = 0; i < 5; i++)
{
for (size_t j = 0; j < 7; j++)
{
cout << matrix[i][j];
}
cout << endl;
}
return 0;
}
'''
As far as I know, when we are resizing a vector using "resize()" over than original capacity, values in original space will remain and new values are assigned to new space.
In the line matrix.resize(5, vector(7, 0)); If we execute that line I thought matrix would be like
1111000
1111000
1111000
0000000
0000000
something like this.
But the programs stops,
I want to know why it won't working.
matrix.resize(5, vector<int>(7, 0));
only add new vector of size 7 not modifying actual vector.
Just resize actual vectors to 7 with:
for (auto &row: matrix) row.resize(7);
so now is working:
1111000
1111000
1111000
0000000
0000000
i tested your codes using an online compiler https://onlinegdb.com/BkwcGuAAD
your columns are not resized (only the rows are resized). running your current code yields
1 1 1 1 0 0 33
1 1 1 1 0 0 33
1 1 1 1 0 0 49 << notice some columns have random numbers?
0 0 0 0 0 0 0
0 0 0 0 0 0 0
try resizing the columns too
matrix[0].resize(7,0);
matrix[1].resize(7,0);
matrix[2].resize(7,0);
matrix.resize(5, vector<int>(7, 0));
you should get something like the following
1 1 1 1 0 0 0
1 1 1 1 0 0 0
1 1 1 1 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
By the C++ Reference
(http://www.cplusplus.com/reference/vector/vector/resize/)
void resize (size_type n);
void resize (size_type n, const value_type& val);
Resizes the container so that it contains n elements.
If n is smaller than the current container size, the content is reduced to its first n elements, removing those beyond (and destroying them).
If n is greater than the current container size, the content is expanded by inserting at the end as many elements as needed to reach a size of n. If val is specified, the new elements are initialized as copies of val, otherwise, they are value-initialized.
If n is also greater than the current container capacity, an automatic reallocation of the allocated storage space takes place.
Notice that this function changes the actual content of the container by inserting or erasing elements from it.
I thought Compiler will understand if I put more longer vector inside of "val".
That is, I thought it would understand this kind of increased "n".
But Compiler will only watch whether "n" parameter itself is changed or not.
Because of this reason, my code wouldn't work properly.
if you want to increase size of vector using size() function, note that you should resize original row values on your hand.

Ordering an array based on 2D array of relations (higher, lower, doesn't matter)

I have been stuck with this problem for two days and I still can't get it right.
Basically, I have a 2D array with relations between certain numbers (in given range):
0 = the order doesn't matter
1 = the first number (number in left column) should be first
2 = the second number (number in upper row) should be first
So, I have some 2D array, for example this:
0 1 2 3 4 5 6
0 0 0 1 0 0 0 2
1 0 0 2 0 0 0 0
2 2 1 0 0 1 0 0
3 0 0 0 0 0 0 0
4 0 0 2 0 0 0 0
5 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0
And my goal is to create a new array of given numbers (0 - 6) in such a way that it is following the rules from the 2D array (e.g. 0 is before 2 but it is after 6). I probably also have to check if such array exists and then create the array. And get something like this:
6 0 2 1 4 5
My Code
(It doesn't really matter, but I prefer c++)
So far I tried to start with ordered array 0123456 and then swap elements according to the table (but that obviously can't work). I also tried inserting the number in front of the other number according to the table, but it doesn't seem to work either.
// My code example
// I have:
// relArr[n][n] - array of relations
// resArr = {1, 2, ... , n} - result array
for (int i = 0; i < n; i++) {
for (int x = 0; x < n; x++) {
if (relArr[i][x] == 1) {
// Finding indexes of first (i) and second (x) number
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
// Placing the (i) before (x) and shifting array
int tmp, insert = iX+1;
if (iX < iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert < iI+1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert++;
}
}
} else if (relArr[i][x] == 2) {
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
int tmp, insert = iX-1;
if (iX > iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert > iI-1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert--;
}
}
}
}
}
I probably miss correct way how to check whether or not it is possible to create the array. Feel free to use vectors if you prefer them.
Thanks in advance for your help.
You seem to be re-ordering the output at the same time as you're reading the input. I think you should parse the input into a set of rules, process the rules a bit, then re-order the output at the end.
What are the constraints of the problem? If the input says that 0 goes before 1:
| 0 1
--+----
0 | 1
1 |
does it also guarantee that it will say that 1 comes after 0?
| 0 1
--+----
0 |
1 | 2
If so you can forget about the 2s and look only at the 1s:
| 0 1 2 3 4 5 6
--+--------------
0 | 1
1 |
2 | 1 1
3 |
4 |
5 |
6 | 1
From reading the input I would store a list of rules. I'd use std::vector<std::pair<int,int>> for this. It has the nice feature that yourPair.first comes before yourPair.second :)
0 before 2
2 before 1
2 before 4
6 before 0
You can discard any rules where the second value is never the first value of a different rule.
0 before 2
6 before 0
This list would then need to be sorted so that "... before x" and "x before ..." are guaranteed to be in that order.
6 before 0
0 before 2
Then move 6, 0, and 2 to the front of the list 0123456, giving you 6021345.
Does that help?
Thanks for the suggestion.
As suggested, only ones 1 are important in 2D array. I used them to create vector of directed edges and then I implemented Topological Sort. I decide to use this Topological Sorting Algorithm. It is basically Topological Sort, but it also checks for the cycle.
This successfully solved my problem.

CUSP sparse library giving strange results

I'm trying to do the following in CUSP:
A=[
1,1,0,0;
2,2,2,0;
0,3,3,3;
0,0,4,4];
B=[1,1,1,1]';
disp(mldivide(A,B));
which is
X=[0.9167,0.0833,-0.5000,0.7500]
On the other hand I get a strange answer from CUSP
#include <cusp/dia_matrix.h>
#include <cusp/krylov/cg.h>
#include <cusp/print.h>
int main()
{
cusp::dia_matrix<int,float,cusp::host_memory> A(4,4,10,3);
A.diagonal_offsets[0] = -1;
A.diagonal_offsets[1] = 0;
A.diagonal_offsets[2] = 1;
for (int i = 0;i <3;i++)
{
for (int q = 0 ;q < A.num_cols;q++)
{
A.values(q,i)=q+1;
}
}
//copy
cusp::dia_matrix<int,float,cusp::device_memory> AA = A;
cusp::array1d<float,cusp::device_memory> BB(A.num_rows,1);
cusp::array1d<float,cusp::device_memory> XX(A.num_rows,0);
cusp::print(AA);
cusp::print(XX);
cusp::print(BB);
cusp::krylov::cg(AA,XX,BB);\
cusp::print(XX);
return 0;
}
The result looks like
sparse matrix <4, 4> with 10 entries
0 0 1
0 1 1
1 0 2
1 1 2
1 2 2
2 1 3
2 2 3
2 3 3
3 2 4
3 3 4
array1d <4>
0
0
0
0
array1d <4>
1
1
1
1
array1d <4>
-39.9938
-53.436
87.9025
-30.1429
The last one doesn't look quite right. Anybody know what I'm doing wrong? Am I using the code wrong or are we supposed to have a really good guessed solution + use a preconditioner?
The conjugate gradient method is only valid for use in symmetric positive definite matrices. Your matrix isn't symmetric. That is why it isn't (and cannot) producing a valid solution. Either use an appropriate, well conditioned SPD matrix, or use a different numerical method.

Why does it cout in something that we doesn't cin in arrays?

When the following program is fead the following input (reading from cin):
1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1
The output is surprising:
1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1
#include<iostream>
using namespace std;
int main()
{
int arey[3][3];
int i,j;
for(j=0;j<=3;j++)
{
for(i=0;i<=3;i++)
{
cin>>arey[j][i];
}
}
arey[0][0]=1;
arey[3][3]=1;
i=0,j=0;
for(j=0;j<=3;j++)
{
for(i=0;i<=3;i++)
{
cout<<arey[j][i];
}
}
return 0;
}
Can someone explain what I should change to get the same output as the input?
Is the matrix 3x3 or 4x4?
you created 3x3 but the loops run for 4 elements and you also update [3][3]
Basically your indexes overflow and you overwrite a different cell in the matrix.
Update: cheecked your input, use: int arey[4][4];
Arrays use 0 based indices, so the valid range of indices for your
int arey[3][3];
are 0 <= i < 3 and 0 <= j < 3
So you need to change the condition in your for loops to be strictly < instead of <=
I really don't think I understand your question, but this is wrong:
int arey[3][3];
...
for(j=0;j<=3;j++) // <= invalid
...
array[3][3]=1; // out of bounds
arey is a 3*3 array. You can't access arey[3][?], that's out of bounds. The only valid indices are 0..2.
Once you've written past the bounds of your array, your program behavior becomes undefined.

Transform an upper triangular matrix into a full matrix C++

How would look the code that can transform an upper triangular matrix into a full matrix.
The matrix is in a vector, not in a bidimensional array...
so the array
[ 1 2 3 4
0 5 6 7
0 0 8 9
0 0 0 10 ]
would become an array like:
[ 1 2 3 4
2 5 6 7
3 6 8 9
4 7 9 10 ]
could you provide some ideas, I was thinking in applying a kind of module or something...
There is one restriction, I am not using bidimensional arrays
I am usng a vector, so is a unidimensional array
First, you must understand the fundemtnal nature of a reflected matrix. For any i, j, the following assertion is true:
m[i][j] ≡ m[j][i]
So, you need some algorithm to make that true. May I suggest:
for(int i = 0; i < HEIGHT; ++i)
for(int j = 0; j < i; ++j)
m[i][j] = m[j][i];
Note the condition of the 2nd loop. By ensuring that j is always less than i, we restrict our activity to the bottom-left triangle.
Next, you must understand how you have implemented a two-dimensional matrix in a one-dimensional array. It appears that you have established the identity:
m[i][j] ≡ v[i*WIDTH+j]
Substituting, we have:
for(int i = 0; i < HEIGHT; ++i)
for(int j = 0; j < i; ++j)
v[i*WIDTH+j] = v[j*WIDTH+i];