I have a matrix in C++, A(n,n) and a vector P(n) which looks something like this:
P = [ 3 6 1 13 12 16 ... ]
it contains numbers 1:n but not in an ascending order but scrambled.
My aim is to change the rows and columns of matrix A to the same order. For example since P[0] = 3 I want the 3rd row and 3rd column to move to the 1st row and column in matrix A.
But because the matrix could be potentially really large, I can't use another matrix of size same as A because that would be wasteful.
In matlab this can be done simply by using the command:
A(P,P);
Any ideas on how to do the same thing in c++?
I will suggest using a level of indirection, to locate each matrix in a cell.
Let's say your matrix object is called M. Instead of using
M[R][C]
to refer to the cell in row R, column C (assuming row-major matrix ordering), you will have an associated pair of vectors, let's call them y and x, so the value of the cell in row R column C is:
M[y[R]][x[C]]
Initially, both y and x vectors map each "logical" row or column to the corresponding physical row and column, that is both y and x contain [0..max_row] and [0..max_col].
Then, to effect the swapping in your question, you simply copy your P vector to the y and x vectors.
You should implement your matrix not directly, as a two-dimensional std::vector, but as a standalone class:
class Matrix {
public:
// ...
auto operator()(size_t R, size_t C) const;
auto &operator()(size_t R, size_t C);
// ...
};
and implement the indirect mapping of rows and columns as part of the class implementation.
Easiest way is probably to just brute-force it. The best idea is probably to do it row by row. You'll need a helper array of length N which keeps track of the original row index, and one temporary row. Then, starting at row R=0, check if row R is in the right position. If not, copy it to the temporary row, copy the right row to row R (permuting it on the go), and copy the temporary row to the spot that was just freed. If a row happens to be in the right spot, copy it to the temporary row, and permute it when copying back.
Related
I'm creating a 2D square matrix in Excel VBA
Dim Matrix(0 To Nrows, 0 To Ncols) as double
and then I pass it as argument ByRef to a function library,
My_foo(Matrix(0,0))
which calls a C++ code. In C++ code I want to access the matrix to get values and make other operations. On this purpose, I read these values as 1D array, so I created an index [R*Ncols + C], where R and C are the element position in 2D representation
void _stdcall My_foo(double* M, long Nrows, long Ncols){
double Value;
R = 10;
C = 0;
Value = M[R*Ncols + C];
}
At this point I expect to find the element having position (10,0), but I find the element (0,10). It seems my matrix is stored with an inverted column/rows order.
It would be enough to set an index like [C*Nrows + R], and access it by column. I tried this and it works, but it contradicts many blogs and posts...
Why? Is it normal?
While C/C++ uses a row-major format to represent multi-dimensional arrays, for other languages different choices were made, so it is not very surprising that Excel VBA uses a column-major format like it is also documented in this forum question.
I am using m.conservativeResize() to do the equivalent in Eigen as the reshape function in MatLab. So let N = 3, and then...
static MatrixXd m(N*N,1);
and then I assign this matrix some values, and it looks like this:
1
1
0
1
0
1
0
1
1
and then try to reshape it...
m.conservativeResize(N,N);
So now the same values should be there, but now in N rows and N columns rather than N*N rows and one column.
However that's not what I get. The first column has the first three values in the column vector - OK so far - but then the remaining values just look like garbage values from uninitialized memory:
1 3.08116e-309 0.420085
1 -2.68156e+154 1.2461e-47
0 -2.68156e+154 0.634626
Any idea what I am doing wrong?
conservativeResize() doesn't ``move" the elements around (in other words, doesn't work like MATLABs reshape, since it performs memory re-allocation even if the initial and final sizes are the same). From the documentation:
Resizes the matrix to rows x cols while leaving old values untouched.
...
Matrices are resized relative to the top-left element. In case values need to be appended to the matrix they will be uninitialized.
These statements seem a bit confusing. What it means is the following: think about the initial matrix as a rectangle, of size A x B. Then think about the resized matrix as another rectangle of size C x D. Then mentally overlap the two rectangles, making sure the top-left corner is common to both. The common elements of the intersection are the ones that are preserved by the conservativeResize. The rest just correspond to uninitialized memory.
In case you want a true reshaping, use resize() instead (making absolutely sure that A x B == C x D, otherwise reallocation takes place and all bets are off).
I have the following problem:
I have a single vector that represents a 2 dimensional matrix, I have the number of rows and the number of columns and few other stuff that are irrelevant.
// A synomon for the type of the grayvalues
typedef unsigned int grayvalue_t;
static_assert(std::numeric_limits<grayvalue_t>::max()<=
std::numeric_limits<size_t>::max(),
"grayvalue_t maximum should be smaller than size_t maximum");
// Number of rows
size_t _R;
// Number of columns
size_t _C;
// Maximum grayvalue
grayvalue_t _MAX_G;
// Pixels' grayvalues
std::vector<grayvalue_t> _pixels;
I'm asked to swap two given rows (given by indices) in O(1), that is not a problem since I can just use memcpy and replace between two continuous blocks of memory, but the problem is that i'm also asked to swap two given columns (again by indices) in O(1) time, but in that case the columns of the matrix aren't continuous blocks of memory in the vector.
/// swaps between rows r1 and r2
/// Time complexity: O(1)
void swap_rows(const size_t& r1, const size_t& r2) {
}
/// swaps between columns c1 and c2
/// Time complexity: O(1)
void swap_cols(const size_t& c1, const size_t& c2) {
}
Am I missing anything?
Would like to get some help.
Thanks!
Like a lot of other CS problems, the answer is: one more layer of indirection.
One option is to maintain a map that maps the column index in the matrix to its actual index in your vector. That is, your matrix columns will not always be stored in order, whereas elements of a row will remain contiguous. The map starts out mapping 0 to 0 1 to 1, and so on. To swap two columns you simply swap their entries in the map. If you also need to traverse the whole array row-wise you will need to consult the map about order of columns.
I am looking for sparse matrix representation that allow for efficient row and column swaping. The classic representation (by compressed row,compressed column or triplets) seems to only allow to perform one or the other but never booth.
Any one know a good data structure for this ?
--Edit--
To clarify , i want to be able to swap rows, like swap row 5 and row 7, and also swap column like swap column 6 and column 8.
You may just want to just add another level of indirection to handle swapping whichever is not efficient. For example, if you have a sparse representation that can efficiently swap rows but not columns, then have an array that maps from the true columns to the effective columns. When you access an element, use the array to find the proper underlying element.
class SparseMatrix {
public:
Element& operator()(Index row,Index col)
{
return matrix(row,col_map[col]);
}
void swapRows(Index row1,Index row2)
{
matrix.swapRows(row1,row2);
}
void swapCols(Index col1,Index col2)
{
swap(col_map[col1],col_map[col2]);
}
private:
FastRowSwapSparseMatrix matrix;
vector<Index> col_map;
};
My suggestion is
Eigen: Very fast and efficient for Linear algebra operations
http://eigen.tuxfamily.org/
or
Mapped Matrix in boost --> more flexible, but slower for linear algebra operations
http://www.boost.org/doc/libs/1_39_0/libs/numeric/ublas/doc/matrix_sparse.htm
For your case, both libraries allow you to manipulate rows and columns efficiently
in OpenCV 2 and later there is method Mat::resize that let's you add any number of rows with the default value to your matrix is there any equivalent method for the column. and if not what is the most efficient way to do this.
Thanks
Use cv::hconcat:
Mat mat;
Mat cols;
cv::hconcat(mat, cols, mat);
Worst case scenario: rotate the image by 90 degrees and use Mat::resize(), making columns become rows.
Since OpenCV, stores elements of matrix rows sequentially one after another there is no direct method to increase column size but I bring up myself two solutions for the above matter,
First using the following method (the order of copying elements is less than other methods), also you could use a similar method if you want to insert some rows or columns not specifically at the end of matrices.
void resizeCol(Mat& m, size_t sz, const Scalar& s)
{
Mat tm(m.rows, m.cols + sz, m.type());
tm.setTo(s);
m.copyTo(tm(Rect(Point(0, 0), m.size())));
m = tm;
}
And the other one if you are insisting not to include even copying data order into your algorithms then it is better to create your matrix with the big number of rows and columns and start the algorithm with the smaller submatrix then increase your matrix size by Mat::adjustROI method.