vector<vector<int>> AsumB(
int kolumny, vector<vector<int>> matrix1, vector<vector<int>> matrix2) {
vector<vector<int>>matrix(kolumny);
matrix = vector<vector<int>>(matrix1.size());
for (int i = 0; i < kolumny; ++i)
for (int j = 0; i <(static_cast<signed int>(matrix1.size())); ++i)
matrix[i][j] = matrix1[i][j] + matrix2[i][j];
return matrix;
}
Please tell me what I don't understand and help me solve this problem
because for 1dimensional vector this kind of description would work;
What about
vector<vector<int>> AsumB(vector<vector<int>> const & matrix1,
vector<vector<int>> const & matrix2) {
vector<vector<int>> matrix(matrix1);
for (std::size_t i = 0U; i < matrix.size(); ++i)
for (std::size_t j = 0U; j < matrix[j].size(); ++j)
matrix[i][j] += matrix2[i][j];
return matrix;
}
?
Unable to reproduce, and OP's reported compiler error doesn't look like it matches the code, so the problem is probably somewhere else.
However, there is a lot wrong here that could be causing all sorts of bad that should be addressed. I've taken the liberty of reformatting the code a bit to make explaining easier
vector<vector<int>> AsumB(int kolumny,
vector<vector<int>> matrix1,
vector<vector<int>> matrix2)
matrix1 and matrix2 are passed by value. There is nothing wrong logically, but this means there is the potential for a lot of unnecessary copying unless the compiler is very sharp.
{
vector<vector<int>> matrix(kolumny);
Declares a vector of vectors with the outer vector sized to kolumny. There are no inner vectors allocated, so 2D operations are doomed.
matrix = vector<vector<int>>(matrix1.size());
Makes a temporary vector of vectors with the outer vector sized to match the outer vector of matrix1. This temporary vector is then assigned to the just created matrix, replacing it's current contents, and is then destroyed. matrix still has no inner vectors allocated, so 2D operations are still doomed.
for (int i = 0; i < kolumny; ++i)
for (int j = 0; i < (static_cast<signed int>(matrix1.size())); ++i)
i and j should never go negative (huge logic problem if they do), so use an unsigned type. Use the right unsigned type and the static_cast is meaningless.
In addition the inner for loop increments and tests i, not j
matrix[i][j] = matrix1[i][j] + matrix2[i][j];
I see nothing wrong here other than matrix having nothing for j to index. This will result in Undefined Behaviour as access go out of bounds.
return matrix;
}
Cleaning this up so that it is logically sound:
vector<vector<int>> AsumB(const vector<vector<int>> & matrix1,
const vector<vector<int>> & matrix2)
We don't need the number of columns. The vector already knows all the sizes involved. A caveat, though: vector<vector<int>> allows different sizes of all of the inner vectors. Don't do this and you should be good.
Next, this function now takes parameters by constant reference.. With the reference there is no copying. With const the compiler knows the vectors will not be changed insode the function and can prevent errors and make a bunch of optimizations.
{
size_t row = matrix1.size();
size_t is an unsigned data type guaranteed to be large enough to index any representable object. It will be bg enough and you don't have to worry about pesky negaitve numbers. Also eliminates the need for any casting later.
if (!(row > 0 && row == matrix2.size()))
{
return vector<vector<int>>();
}
Here we make sure that everyone agrees ont he number of rows inviolved and return an empty vector if they don't. You could also throw an exception. The exception may be a better solution, but I don't know the use case.
size_t column = matrix1[0].size();
if (!(column > 0 && column == matrix2[0].size()))
{
return vector<vector<int>>();
}
Dowes the same as above, but makes sure the number of columns makes sense.
vector<vector<int>> matrix(row, vector<int>(column));
Created a local row by column matrix to store the result. Note the second parameter. vector<int>(column) tells the compiler that all row inner vectors will be initialized to a vector of size column.
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < column; ++j)
{
Here we simplified the loops just a bit since we know all the sizes.
matrix[i][j] = matrix1[i][j] + matrix2[i][j];
}
}
return matrix;
The compiler has a number of tricks at its disposal to eliminate copying matrix on return. Look up Return Value Optimization with your preferred web search engine if you want to know more.
}
All together:
vector<vector<int>> AsumB(const vector<vector<int>> & matrix1,
const vector<vector<int>> & matrix2)
{
size_t row = matrix1.size();
if (!(row > 0 && row == matrix2.size()))
{
return vector<vector<int>>();
}
size_t column = matrix1[0].size();
if (!(column > 0 && column == matrix2[0].size()))
{
return vector<vector<int>>();
}
vector<vector<int>> matrix(row, vector<int>(column));
for (int i = 0; i < row; ++i)
{
for (int j = 0; j < column; ++j)
{
matrix[i][j] = matrix1[i][j] + matrix2[i][j];
}
}
return matrix;
}
Related
I'm implementing sparse matrices multiplication(type of elements std::complex) after converting them to CSR(compressed sparse row) format and I'm using openmp for this, but what I noticed that increasing the number of threads doesn't necessarily increase the performance, sometimes is totally the opposite! why is that the case? and what can I do to solve the issue?
typedef std::vector < std::vector < std::complex < int >>> matrix;
struct CSR {
std::vector<std::complex<int>> values; //non-zero values
std::vector<int> row_ptr; //pointers of rows
std::vector<int> cols_index; //indices of columns
int rows; //number of rows
int cols; //number of columns
int NNZ; //number of non_zero elements
};
const matrix multiply_omp (const CSR& A,
const CSR& B,const unsigned int num_threds=4) {
if (A.cols != B.rows)
throw "Error";
CSR B_t = sparse_transpose(B);
omp_set_num_threads(num_threds);
matrix result(A.rows, std::vector < std::complex < int >>(B.cols, 0));
#pragma omp parallel
{
int i, j, k, l;
#pragma omp for
for (i = 0; i < A.rows; i++) {
for (j = 0; j < B_t.rows; j++) {
std::complex < int > sum(0, 0);
for (k = A.row_ptr[i]; k < A.row_ptr[i + 1]; k++)
for (l = B_t.row_ptr[j]; l < B_t.row_ptr[j + 1]; l++)
if (A.cols_index[k] == B_t.cols_index[l]) {
sum += A.values[k] * B_t.values[l];
break;
}
if (sum != std::complex < int >(0, 0)) {
result[i][j] += sum;
}
}
}
}
return result;
}
You can try to improve the scaling of this algorithm, but I would use a better algorithm. You are allocating a dense matrix (wrongly, but that's beside the point) for the product of two sparse matrices. That's wasteful since quite often the project of two sparse matrices will not be dense by a long shot.
Your algorithm also has the wrong time complexity. The way you search through the rows of B means that your complexity has an extra factor of something like the average number of nonzeros per row. A better algorithm would assume that the indices in each row are sorted, and then keep a pointer for how far you got into that row.
Read the literature on "Graph Blas" for references to efficient algorithms.
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
for (i = 0; i < m[i].size(); i++)
{
for(j = 0; j < m[j].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
I am making a program that will do a whole lot of matrix manipulation, and this section is crashing and I don't exactly know why. I have narrowed it down to the line:
newMatrix[i][j] = m[i][j];
It crashes right here, and I am not sure why.
In addition to what #Saurav posted, newMatrix is empty so you cannot assign values to newMatrix[i][j]. You can fix this by initializing the vectors with a given size:
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m.size());
int i,j;
for (i = 0; i < m.size(); i++)
{
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Before the for-loops we initialize newMatrix to have m.size() many empty vectors inside of it (the vectors are empty due to their default constructor). During each iteration of the outer for-loop we ensure that each vector within newMatrix has the correct size using the resize member function.
Note that if you want a copy of a vector you can simply just write:
vector< vector<int> > newMatrix(m);
Your checks are wrong. Instead it should be
for (i = 0; i < m.size(); i++) // m.size() gives the number of rows
{
for(j = 0; j < m[i].size(); j++) // m[i].size() gives the number of columns in the row
You're assigning into your new newMatrix without setting its size first. It will default to empty, and any attempt to assign to it will result in undefined behavior.
Since you don't pass in a new size, it's hard to know exactly what you're trying to accomplish. That's why I don't have more explicit advice on how to fix it.
If you want to allocate vector of vector, the you need to allocate memory for the matrix before you index on it. So you will have to use something like
newMatrix.resize(size);
for (int i = 0; i < size; ++i) {
newMatrix[i].resize(size);
}
Or you could use .push_back() vector method to add values to the vector without allocating memory beforehand.
vectors operator[] returns a reference to the specified element without bounds checking.
That means it does not magically resize the vector, or perform any other operations to ensure the element exists. If the element does not exist, the result is undefined behaviour - which means means anything can happen. Practically, it often causes the program to access an invalid memory location, which causes a crash.
The above is true even for a simple vector<int>. You've compounded your problems by working with a vector<vector<int> > (Each element of a vector<vector<int> > is a vector<int>).
Your function is actually a little breathtaking in the number of times it potentially invokes undefined behaviour. You happen to be getting a crash on the statement newMatrix[i][j] = m[i][j], but the potential for undefined behaviour actually occurs before then.
In the outer loop, m[i] will not exist if m.size() (which your code doesn't check) has a value zero. If m.size() is zero, that causes the evaluation of m[i] (as m.operator[](i)) to have undefined behaviour.
Essentially, you need to ensure any index i is valid before evaluating m[i], and then ALSO ensure that j is a valid index of m[i] before evaluating m[i][j]. And then do the same for newMatrix. Your code does none of this at all. A more correct rendering of your function (assuming the intent is to create a copy of m) is
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
newMatrix.resize(m.size()); // necessary to ensure we can access newMatrix[i] in the loop below
for (i = 0; i < m.size(); i++) // ensure i is a valid index of m
{
// newMatrix[i].size() is still zero, so we need to resize for use in the inner loop
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++) // ensure j is a valid index of m[i]
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Now, the thing is, your code is actually recreating functionality that vector provides already. So, we could replace the body of the function quite simply with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m);
return newMatrix;
}
or even with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
return m;
}
This means your function (as I've modified it) is misnamed - it doesn't resize anything. In fact, it is rather pointless since, if the caller does this
x = resizeVector(y);
it could achieve the same effect without your function at all, simply as
x = y;
which is also more efficient (no function call, no creating copies to pass by value, etc).
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
for (i = 0; i < m[i].size(); i++)
{
for(j = 0; j < m[j].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
I am making a program that will do a whole lot of matrix manipulation, and this section is crashing and I don't exactly know why. I have narrowed it down to the line:
newMatrix[i][j] = m[i][j];
It crashes right here, and I am not sure why.
In addition to what #Saurav posted, newMatrix is empty so you cannot assign values to newMatrix[i][j]. You can fix this by initializing the vectors with a given size:
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m.size());
int i,j;
for (i = 0; i < m.size(); i++)
{
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Before the for-loops we initialize newMatrix to have m.size() many empty vectors inside of it (the vectors are empty due to their default constructor). During each iteration of the outer for-loop we ensure that each vector within newMatrix has the correct size using the resize member function.
Note that if you want a copy of a vector you can simply just write:
vector< vector<int> > newMatrix(m);
Your checks are wrong. Instead it should be
for (i = 0; i < m.size(); i++) // m.size() gives the number of rows
{
for(j = 0; j < m[i].size(); j++) // m[i].size() gives the number of columns in the row
You're assigning into your new newMatrix without setting its size first. It will default to empty, and any attempt to assign to it will result in undefined behavior.
Since you don't pass in a new size, it's hard to know exactly what you're trying to accomplish. That's why I don't have more explicit advice on how to fix it.
If you want to allocate vector of vector, the you need to allocate memory for the matrix before you index on it. So you will have to use something like
newMatrix.resize(size);
for (int i = 0; i < size; ++i) {
newMatrix[i].resize(size);
}
Or you could use .push_back() vector method to add values to the vector without allocating memory beforehand.
vectors operator[] returns a reference to the specified element without bounds checking.
That means it does not magically resize the vector, or perform any other operations to ensure the element exists. If the element does not exist, the result is undefined behaviour - which means means anything can happen. Practically, it often causes the program to access an invalid memory location, which causes a crash.
The above is true even for a simple vector<int>. You've compounded your problems by working with a vector<vector<int> > (Each element of a vector<vector<int> > is a vector<int>).
Your function is actually a little breathtaking in the number of times it potentially invokes undefined behaviour. You happen to be getting a crash on the statement newMatrix[i][j] = m[i][j], but the potential for undefined behaviour actually occurs before then.
In the outer loop, m[i] will not exist if m.size() (which your code doesn't check) has a value zero. If m.size() is zero, that causes the evaluation of m[i] (as m.operator[](i)) to have undefined behaviour.
Essentially, you need to ensure any index i is valid before evaluating m[i], and then ALSO ensure that j is a valid index of m[i] before evaluating m[i][j]. And then do the same for newMatrix. Your code does none of this at all. A more correct rendering of your function (assuming the intent is to create a copy of m) is
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
newMatrix.resize(m.size()); // necessary to ensure we can access newMatrix[i] in the loop below
for (i = 0; i < m.size(); i++) // ensure i is a valid index of m
{
// newMatrix[i].size() is still zero, so we need to resize for use in the inner loop
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++) // ensure j is a valid index of m[i]
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Now, the thing is, your code is actually recreating functionality that vector provides already. So, we could replace the body of the function quite simply with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m);
return newMatrix;
}
or even with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
return m;
}
This means your function (as I've modified it) is misnamed - it doesn't resize anything. In fact, it is rather pointless since, if the caller does this
x = resizeVector(y);
it could achieve the same effect without your function at all, simply as
x = y;
which is also more efficient (no function call, no creating copies to pass by value, etc).
I have a vector of N objects, and I would like to iterate through all neighbor permutations of this vector. What I call a neighbor permutation is a permutation where only two elements of the original vector would be changed :
if I have a vector with 'a','b','c','d' then :
'b','a','c','d' //is good
'a','c','b','d' //is good
'b','a','d','c' //is not good (2 permutations)
If I use std::next_permutation(myVector.begin(), myVector.end() then I will get all the possible permutations, not only the "neighbor" ones...
Do you have any idea how that could be achieved ?
Initially, I thought I would filter the permutations that have a hamming distance greater than 2.
However, if you really only need to generate all the vectors resulting by swapping one pair, it would be more efficient if you do like this:
for(int i = 0; i < n; i++)
for(int j = i + 1; j < n; j++)
// swap i and j
Depending on whether you need to collect all the results or not, you should make a copy or the vector before the swap, or swap again i and j after you processed the current permutation.
Collect all the results:
std::vector< std::vector<T> > neighbor_permutations;
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
std::vector<T> perm(v);
std::swap(perm[i], perm[j]);
neighbor_permutations.push_back(perm);
}
}
Faster version - do not collect results:
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
std::swap(v[i], v[j]);
process_permutation(v);
std::swap(v[i], v[j]);
}
}
Perhaps it's a good idea to divide this into two parts:
How to generate the "neighbor permutations"
How to iterate over them
Regarding the first, it's easy to write a function:
std::vector<T> make_neighbor_permutation(
const std::vector<T> &orig, std::size_t i, std::size_t j);
which swaps i and j. I did not understand from your question if there's an additional constraint that j = i + 1, in which case you could drop a parameter.
Armed with this function, you now need an iterator that iterates over all legal combinations of i and j (again, I'm not sure of the interpretation of your question. It might be that there are n - 1 values).
This is very easy to do using boost::iterator_facade. You simply need to define an iterator that takes in the constructor your original iterator, and sets i (and possibly j) to initial values. As it is incremented, it needs to update the index (or indices). The dereference method needs to call the above function.
Another way to get it, just a try.
int main()
{
std::vector<char> vec={'b','a','c','d'};
std::vector<int> vec_in={1,1,0,0};
do{
auto it =std::find(vec_in.begin(),vec_in.end(),1);
if( *(it++) ==1)
{
for(auto &x : vec)
{
std::cout<<x<<" ";
}
std::cout<<"\n";
}
} while(std::next_permutation(vec_in.begin(),vec_in.end()),
std::next_permutation(vec.begin(),vec.end()) );
}
I want to do a function that given 2 matrix returns the sum of both.I think the problem is in how I initialize the Matrix 't'.
#include <iostream>
#include <vector>
using namespace std;
typedef vector< vector<int> > Matrix;
Matrix sum(const Matrix&a,const Matrix&b){
Matrix t;
for(int i=0;i<a.size();i++)
for(int j=0;j<a.size();j++)
t[i][j] = a[i][j] + b[i][j];
return t;
}
You'll need to initialize the rows and columns of t with something like:
Matrix t = vector< vector<int> >(row_count, vector<int>(col_count, 0));
That will make a row_count by col_count matrix filled with zeroes.
On a side note about performance: comparing to .size() in a for loop means that before each iteration, .size() has to be calculated again. You can save a bit of processing (which adds up for massive data sets) by pre-calculating it like so:
for (int row = 0, row_ct = mat.size(); row < row_ct; ++row)
You don't have a rectangular data set in general: each a[i] is a vector of a possibly different length. Supposing you do in fact take care to have a rectangular grid, your for loop is still off; it should be like this:
for (int i = 0; i < a.size(); i++)
{
assert(a.size() <= b.size() && a.size() <= t.size());
for (int j = 0; j < a[i].size(); j++) // !!
{
assert(a[i].size() <= b[i].size() && a[i].size() <= t[i].size());
t[i][j] = a[i][j] + b[i][j];
}
}
I added some assertions to indicate which preconditions you have to satisfy.
To initialize a rectangular array, you can do something like this:
std::vector<std::vector<int>> v(n_rows, std::vector<int>(n_cols, 0));