swapping two columns in a matrix represented by vector - c++

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.

Related

Minimum of a matrix in C++

I have a std::vector<std::vector<type T>> matrix, I insert elements of type T to this matrix and I do some instructions by line on these elements. I need also at each iteration to delete the element with a minimum cost.
I created an std::priority_queue<Costelement, std::vector<Costelement>, Costelement::Comparekeys> Costvec; where:
struct Costelement
{
int row;
int column;
std::vector<double> cost;
struct CompareCosts
{
bool operator()(const Costelement &e1, const Costelement &e2)
{
return (e1.cost > e2.cost);
}
};
};
where row and column are the position of the element in matrix having the corresponding cost. However, when I delete the element with minimum key from matrix, the positions of the elements in the corresponding row change. I used std::min_element at each iteration on matrix but this was very costly. How can we model efficiently this case?
A std::priority_queue by default is just a std::vector that is kept in a sorted state. It can still be expensive to insert and remove elements from the queue, and as you noticed, you would potentially need to update all of the Costelements in the queue when you insert or remove an element from matrix in order to relect the new positions. However, you can make that a bit more efficient by making the priority queue two-dimensional as well, something that looks like:
std::priority_queue<std::priority_queue<Costelement, ...>, ...> cost_matrix;
Basically, the inner priority queue sort the cost of the columns of a single row, the outer priority queue should then sort the cost of whole rows. Let's create ColumnCost and RowCost structs:
struct ColumnCost {
int column;
double cost;
friend bool operator<(const ColumnCost &a, const ColumnCost &b) {
return a.cost > b.cost;
}
};
struct RowCost {
int row;
std::priority_queue<ColumnCost> columns;
friend bool operator<(const RowCost &a, const RowCost &b) {
return a.columns.top() > b.columns.top();
}
};
std::priority_queue<RowCost> cost_matrix;
Now you can easily get the lowest cost element from costmatrix, which returns the RowCost which contains the lowest cost element, and then you get the ColumnCost with the lowest cost from that one:
const auto &lowest_row = cost_matrix.top();
const auto &lowest_column = lowest_row.columns.top();
int row = lowest_row.row;
int column = lowest_column.column;
When you now insert or delete an element from matrix, you insert or delete from cost_matrix in the same way. You still need to update row or column coordinates, but now it is much less work. The only thing to be aware of is that if you update add or remove an element to the priority queue of a RowCost, you need to delete and re-insert that whole row from cost_matrix to ensure the outer priority queue is kept correctly sorted.
Another possible optimization is to use a std::priority_queue to keep the rows sorted, but use std::min_element() to keep track of the minimum of each individual row. This greatly reduces the amount of memory necessary to store the cost_matrix, and you would only need to call std::min_element() to recalculate the minimum cost element of a row when you change that row.
You may want to replace a row vector with a rope (see the rope data structure in Wikipedia).
It's a binary tree based structure, which allows quite efficient removing elements and searching for an n-th element ('indexing'), so you needn't update positions in all elements when you remove one of them.

Reordering of matrix in c++

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.

How to select a column from a row-major array in sub-linear time?

Lets say that I'm given a row major array.
int* a = (int *)malloc( 9 x 9 x sizeof(int));
Look at this as a 2D 9x9 array where a (row,column) index corresponds to [row * 9 + column]
Is there a way where I can select a single column from this array in sub-linear time?
Since the columns wont be contiguous, we cant do a direct memcpy like we do to get a single row.
The linear-time solution would be obvious I guess, but I'm hoping for some sub-linear solution.
Thanks.
It is not clear what you mean by sublinear. If you consider the 2D array as NxN size, then sublinear on N is impossible. To copy N elements you need to perform N copy operations, the copy will be linear on the number of elements being copied.
The comment about memcpy seem to indicate that you mistakenly believe that memcpy is sublinear on the number of elements being copied. It is not. The advantage of memcpy is that the constant hidden in the big-O notation is small, but the operation is linear on the size of the memory being copied.
The next question is whether the big-O analysis actually makes sense. If your array is 9x9, then the effect hidden in the constant of the big-O notation can be more important than the complexity.
I don't really get what you mean but consider:
const size_t x_sz=9;
size_t x=3, y=6; //or which ever element you wish to access
int value=a[Y*x_sz+x];
this will be a constant time O(1) expression. It must calculate the offset and load the value.
to iterate through every value in a column:
const size_t x_sz=9, y_sz=9;
size_t x=3; //or which ever column you wish to access
for(size_t y=0; y!=y_sz; ++y){
int value=a[Y*x_sz+x];
//value is current column value
}
again each iteration is constant time, the whole iteration sequence is therefore O(n) (linear), note that it would still be linear if it was contiguous.

Super long arrays in C++

I have two sets A and B. Set A contains unique elements. Set B contains all elements. Each element in the B is a 10 by 10 matrix where all entries are either 1 or 0. I need to scan through set B and everytime i encounter a new matrix i will add it to set A. Therefore set A is a subset of B containing only unique matrices.
It seems like you might really be looking for a way to manage a large, sparse array. Trivially, you could use a hash map with your giant index as your key, and your data as the value. If you talk more about your problem, we might be able to find a more appropriate data structure for your problem.
Update:
If set B is just some set of matrices and not the set of all possible 10x10 binary matrices, then you just want a sparse array. Every time you find a new matrix, you compute its key (which could simply be the matrix converted into a 100 digit binary value, or even a 100 character string!), look up that index. If no such key exists, insert the value 1 for that key. If the key does exist, increment and re-store the new value for that key.
Here is some code, maybe not very efficient :
# include <vector>
# include <bitset>
# include <algorithm>
// I assume your 10x10 boolean matrix is implemented as a bitset of 100 bits.
// Comparison of bitsets
template<size_t N>
class bitset_comparator
{
public :
bool operator () (const std::bitset<N> & a, const std::bitset<N> & b) const
{
for(size_t i = 0 ; i < N ; ++i)
{
if( !a[i] && b[i] ) return true ;
else if( !b[i] && a[i] ) return false ;
}
return false ;
}
} ;
int main(int, char * [])
{
std::set< std::bitset<100>, bitset_comparator<100> > A ;
std::vector< std::bitset<100> > B ;
// Fill B in some manner ...
// Keeping unique elements in A
std::copy(B.begin(), B.end(), std::inserter(A, A.begin())) ;
}
You can use std::listinstead of std::vector. The relative order of elements in B is not preserved in A (elements in A are sorted).
EDIT : I inverted A and B in my first post. It's correct now. Sorry for the inconvenience. I also corrected the comparison functor.
Each element in the B is a 10 by 10 matrix where all entries are either 1 or 0.
Good, that means it can be represented by a 100-bit number. Let's round that up to 128 bits (sixteen bytes).
One approach is to use linked lists - create a structure like (in C):
typedef struct sNode {
unsigned char bits[16];
struct sNode *next;
};
and maintain the entire list B as a sorted linked list.
The performance will be somewhat less (a) than using the 100-bit number as an array index into a truly immense (to the point of impossible given the size of the known universe) array.
When it comes time to insert a new item into B, insert it at its desired position (before one that's equal or greater). If it was a brand new one (you'll know this if the one you're inserting before is different), also add it to A.
(a) Though probably not unmanageably so - there are options you can take to improve the speed.
One possibility is to use skip lists, for faster traversal during searches. These are another pointer that references not the next element but one 10 (or 100 or 1000) elements along. That way you can get close to the desired element reasonably quickly and just do the one-step search after that point.
Alternatively, since you're talking about bits, you can divide B into (for example) 1024 sub-B lists. Use the first 10 bits of the 100-bit value to figure out which sub-B you need to use and only store the next 90 bits. That alone would increase search speed by an average of 1000 (use more leading bits and more sub-Bs if you need improvement on that).
You could also use a hash on the 100-bit value to generate a smaller key which you can use as an index into an array/list, but I don't think that will give you any real advantage over the method in the previous paragraph.
Convert each matrix into a string of 100 binary digits. Now run it through the Linux utilities:
sort | uniq
If you really need to do this in C++, it is possible to implement your own merge sort, then the uniq part becomes trivial.
You don't need N buckets where N is the number of all possible inputs. A binary tree will just do fine. This is implemented with set class in C++.
vector<vector<vector<int> > > A; // vector of 10x10 matrices
// fill the matrices in A here
set<vector<vector<int> > > B(A.begin(), A.end()); // voila!
// now B contains all elements in A, but only once for duplicates

Sorting eigenvectors by their eigenvalues (associated sorting)

I have an unsorted vector of eigenvalues and a related matrix of eigenvectors. I'd like to sort the columns of the matrix with respect to the sorted set of eigenvalues. (e.g., if eigenvalue[3] moves to eigenvalue[2], I want column 3 of the eigenvector matrix to move over to column 2.)
I know I can sort the eigenvalues in O(N log N) via std::sort. Without rolling my own sorting algorithm, how do I make sure the matrix's columns (the associated eigenvectors) follow along with their eigenvalues as the latter are sorted?
Typically just create a structure something like this:
struct eigen {
int value;
double *vector;
bool operator<(eigen const &other) const {
return value < other.value;
}
};
Alternatively, just put the eigenvalue/eigenvector into an std::pair -- though I'd prefer eigen.value and eigen.vector over something.first and something.second.
I've done this a number of times in different situations. Rather than sorting the array, just create a new array that has the sorted indices in it.
For example, you have a length n array (vector) evals, and a 2d nxn array evects. Create a new array index that has contains the values [0, n-1].
Then rather than accessing evals as evals[i], you access it as evals[index[i]] and instead of evects[i][j], you access it evects[index[i]][j].
Now you write your sort routine to sort the index array rather than the evals array, so instead of index looking like {0, 1, 2, ... , n-1}, the value in the index array will be in increasing order of the values in the evals array.
So after sorting, if you do this:
for (int i=0;i<n;++i)
{
cout << evals[index[i]] << endl;
}
you'll get a sorted list of evals.
this way you can sort anything that's associated with that evals array without actually moving memory around. This is important when n gets large, you don't want to be moving around the columns of the evects matrix.
basically the i'th smallest eval will be located at index[i] and that corresponds to the index[i]th evect.
Edited to add. Here's a sort function that I've written to work with std::sort to do what I just said:
template <class DataType, class IndexType>
class SortIndicesInc
{
protected:
DataType* mData;
public:
SortIndicesInc(DataType* Data) : mData(Data) {}
Bool operator()(const IndexType& i, const IndexType& j) const
{
return mData[i]<mData[j];
}
};
The solution purely relies on the way you store your eigenvector matrix.
The best performance while sorting will be achieved if you can implement swap(evector1, evector2) so that it only rebinds the pointers and the real data is left unchanged.
This could be done using something like double* or probably something more complicated, depends on your matrix implementation.
If done this way, swap(...) wouldn't affect your sorting operation performance.
The idea of conglomerating your vector and matrix is probably the best way to do it in C++. I am thinking about how I would do it in R and seeing if that can be translated to C++. In R it's very easy, simply evec<-evec[,order(eval)]. Unfortunately, I don't know of any built in way to perform the order() operation in C++. Perhaps someone else does, in which case this could be done in a similar way.