Using std::max_element on a two dimensional matrix - c++

I have a two dimensional matrix
double TotalEnergy[200][47];
This matrix is populated with appropriate values. Now I am trying to find maximum value in each column.
How do I use std::max_element in this case?
Many thanks.
Best Regards
Chintan

Convert each individual column into a std::vector and use the std::max_element function on the vector. STL containers take care of all memory issues very efficiently without us having to worry about it.
double maxElements[47]; //This will contain the max of each column of TotalEnergy
std::vector<double> vec;
for(int k=0; k<47; k++)
{
for(int l=0; l<200;l++)
vec.push_back(TotalEnergy[l][k]);
maxElements[k] = *std::max_element(vec.begin() , vec.end());
vec.clear();
}

According to cppreference std::max_elements only works with iterators. Unless you want to create an iterator that walks every element of a 2D matrix, I suggest running std::max_element for every row (or column) of the matrix.
Example (untested) code:
double result{std::numeric_limits<double>::min()};
for(int iX{0}; iX < 200; ++iX) {
result = std::max(result, std::max_element(std::begin(TotalEnergy[iX]),
std::end(TotalEnergy[iX])));
}

You can make sure you are using pointers to first and last+1 elements:
double distBetweenNodes[N][N];
const double maxDist = *std::max_element(&distBetweenNodes[0][0], &distBetweenNodes[0][0]+N*N);
// Note that &distBetweenNodes[0][0]+P*N could be &distBetweenNodes[N][N]

I just found that we can do this:
const int n = 555; // for example
int arr[n][n];
// filling the array
int mx = *max_element(begin(arr[0]), end(arr[n-1]));

Related

Create 2D vector from 2 1D vectors

I am fairly new to vectors and I'm trying to populate a 2D vector from 2 1D vectors for coordinate points. I have 2 vectors like this where source_x and source_y contains values from a file:
std::vector<float,T<float>> pos_x(5);
std::vector<float,T<float>> pos_y(5);
for (int i = 0; i < 5 ; i++){
pos_x[i] = i+1; //{1,2,3,4,5}
}
for (int i = 0; i < num ; i++){
pos_y[i] = i+1 ; //{1,2,3,4,5}
}
I created my 2D vector like this:
std::vector<std::vector<float, T<float>>> position;
for (int i = 0; i < num ; i++){
for (int j = 0; j < num ; i++){
//Output expected: {{1,2,3,4,5},{1,2,3,4,5}}
position[i][j] = //I'm confuse here
}
}
I am not certain how to populate pos_x to position[i] and pos_y to position[j].
Thank you
So my guess is this
std::vector<std::vector<float>> position(num, std::vector<float>(2));
for (int i = 0; i < num ; i++){
position[i][0] = pos_x[i];
position[i][1] = pos_y[i];
}
But I could easily be wrong.
UPDATE based on the example in the question I now think this is the correct code
std::vector<std::vector<float>> position(2, std::vector<float>(num));
for (int i = 0; i < num ; i++){
position[0][i] = pos_x[i];
position[1][i] = pos_y[i];
}
There's no such thing as a 2D vector. The truth is that you can create a vector that contains vectors. The first vector is used as an index in the collected vectors.
Note that this concept is similar to a 2D array: arr[3][4] means 3 indices, each one points to 4 data.
To create such 2D vector:
std::vector< std::vector <float>> positions.
Notice I didn't use the second parameter (as in std::vector<float, SomeAllocator> because we don't need this custom memory allocator.
Also notice that, contrary to arrays, I did't tell anything about the sizes of each vector, because the std::vector will take care of it.
Let's populate it.
The "main" vector contains vectors. So these secondary vectors may be created before stored in the "main" one.
std::vector<float> v1; //secondary
positions.push_back(v1); //add it to main vector
Put some values in the secondary:
v1.push_back(7.5);
v1.push_back(-3.1);
Another way is to access through the main vector. If we new this main vector contains v1 in its first index:
positions[0].push_back(8.); // same as v1.push_back(8.) if positions[0] refers to v1
or better using "at": positions.at(0).push_back(8.);
Change some value:
v1.at(1) = 66.88;
or
positions[0].at(1) = 66.88;
You can also do v1[1] = 66.88 but prefer the at() methof because it will check that index "1" is allowed by the size of the vector v1.
You can create and add another secondary vector:
std::vector<float> v2; //secondary
positions.push_back(v2); //add it to main vector
and work with it the same as with previous v1. Now, positions[1] refers to v2
I leave the rest of pulling from other vectors to you.

Vector dot product in Microsoft SEAL with CKKS

I am currently trying to implement matrix multiplication methods using the Microsoft SEAL library. I have created a vector<vector<double>> as input matrix and encoded it with CKKSEncoder. However the encoder packs an entire vector into a single Plaintext so I just have a vector<Plaintext> which makes me lose the 2D structure (and then of course I'll have a vector<Ciphertext> after encryption). Having a 1D vector allows me to access only the rows entirely but not the columns.
I managed to transpose the matrices before encoding. This allowed me to multiply component-wise the rows of the first matrix and columns (rows in transposed form) of the second matrix but I am unable to sum the elements of the resulting vector together since it's packed into a single Ciphertext. I just need to figure out how to make the vector dot product work in SEAL to perform matrix multiplication. Am I missing something or is my method wrong?
It has been suggested by KyoohyungHan in the issue: https://github.com/microsoft/SEAL/issues/138 that it is possible to solve the problem with rotations by rotating the output vector and summing it up repeatedly.
For example:
// my_output_vector is the Ciphertext output
vector<Ciphertext> rotations_output(my_output_vector.size());
for(int steps = 0; steps < my_output_vector.size(); steps++)
{
evaluator.rotate_vector(my_output_vector, steps, galois_keys, rotations_output[steps]);
}
Ciphertext sum_output;
evaluator.add_many(rotations_output, sum_output);
vector of vectors is not the same as an array of arrays (2D, matrix).
While one-dimentional vector<double>.data() points to contiguous memory space (e.g., you can do memcpy on that), each of "subvectors" allocates own, separate memory buffer. Therefore vector<vector<double>>.data() makes no sense and cannot be used as a matrix.
In C++, two-dimensional array array2D[W][H] is stored in memory identically to array[W*H]. Therefore both can be processed by the same routines (when it makes sense). Consider the following example:
void fill_array(double *array, size_t size, double value) {
for (size_t i = 0; i < size; ++i) {
array[i] = value;
}
}
int main(int argc, char *argv[])
{
constexpr size_t W = 10;
constexpr size_t H = 5;
double matrix[W][H];
// using 2D array as 1D to fill all elements with 5.
fill_array(&matrix[0][0], W * H, 5);
for (const auto &row: matrix) {
for (const auto v : row) {
cout << v << '\t';
}
cout << '\n';
}
return 0;
}
In the above example, you can substitute double matrix[W][H]; with vector<double> matrix(W * H); and feed matrix.data() into fill_array(). However, you cannot declare vector(W) of vector(H).
P.S. There are plenty of C++ implementations of math vector and matrix. You can use one of those if you don't want to deal with C-style arrays.

How to initialize an empty global vector in C++

I have a general question. Hopefully, one of you has a good approach to solve my problem. How can I initialize an empty vector?
As far as I read, one has to know the size of an array at compiling time, though for vectors it is different. Vectors are stored in the heap (e.g. here: std::vector versus std::array in C++)
In my program I want to let the client decide how accurate interpolation is going to be done. That's why I want to use vectors.
The problem is: For reasons of clear arrangement I want to write two methods:
one method for calculating the coefficients of an vector and
one method which is providing the coefficients to other functions.
Thus, I want to declare my vector as global and empty like
vector<vector<double>> vector1;
vector<vector<double>> vector2;
However, in the method where I determine the coefficients I cannot use
//vector containing coefficients for interpolation
/*vector<vector<double>>*/ vector1 (4, vector<double>(nn - 1));
for (int ii = 0; ii < nn - 1; ii++) {vector1[ii][0] = ...;
}
"nn" will be given by the client when running the program. So my question is how can I initialize an empty vector? Any ideas are appreciated!
Note please, if I call another function which by its definition gives back a vector as a return value I can write
vector2= OneClass.OneMethod(SomeInputVector);
where OneClass is an object of a class and OneMethod is a method in the class OneClass.
Note also, when I remove the comment /**/ in front of the vector, it is not global any more and throws me an error when trying to get access to the coefficients.
Use resize:
vector1.resize(4, vector<double>(nn - 1));
Use resize() function as follows:
vector<vector<double>> v;
int f(int nn){
v.resize(4);
for(int i = 0; i < 4; i++){
v[i].resize(nn - 1);
}
}
It look to me that you're actually asking how to add items to your global vector. If so this might help:
//vector containing coefficients for interpolation
for (int i = 0; i < 4; ++i)
vector1.push_back(vector<double>(nn - 1));
for (int ii = 0; ii < nn - 1; ii++)
{
vector1[ii][0] = ...;
}
Unsure if it is what you want, but assign could be interesting :
vector<vector<double>> vector1; // initialises an empty vector
// later in the code :
vector<double> v(nn -1, 0.); // creates a local vector of size 100 initialized with 0.
vector1.assign(4, v); // vector1 is now a vector of 4 vectors of 100 double (currently all 0.)

c++ matrix insert value using iterators (homework)

I'm pretty new to C++ and got an assignment to make a matrix using only STL containers. I've used a vector (rows) of vectors (columns). The problem I'm having is in the 'write' operation - for which I may only use an iterator-based implementation. Problem is, quite simply: it writes nothing.
I've tested with a matrix filled with different values, and while the iterator ends up on exactly the right spot, it doesn't change the value.
Here's my code:
void write(matrix mat, int row, int col, int input)
{
assert(row>=0 && col>=0);
assert(row<=mat.R && col<=mat.C);
//I set up the iterators.
vector<vector<int> >::iterator rowit;
vector<int>::iterator colit;
rowit = mat.rows.begin();
//I go to the row.
for(int i = 0; i<row-1; ++i)
{
++rowit;
}
colit = rowit->begin();
//I go to the column.
for(int j = 0; j<col-1; ++j)
{
++colit;
}
*colit = input; //Does nothing.
}
What am I overlooking?
Thanks.
matrix mat is a parameter by value, it copies the matrix and hence you are writing to a copy.
You should pass the matrix by reference instead, like matrix & mat.
But wait... You are passing the matrix every time as the first parameter, this is a bad sign!
This usually indicates that the parameter should be turned into an object on which you can run the methods; that way, you don't need to pass the parameter at all. So, create a Matrix class instead.
Please note that there is std::vector::operator[].
So, you could just do it like this:
void write(matrix & mat, int row, int col, int input)
{
assert(row>=0 && col>=0);
assert(row<=mat.R && col<=mat.C);
mat[row][col] = input;
}

swapping an inner and outer vector

I have a vector of vector of myObjects defined, creating essentially a 2D array. I would like to transpose this array such that rows become columns and columns become rows. Obviously I could do this in a double for-loop, but this seems massively inelegant and will be pretty slow. I was wondering if there's something clever in C++ or the STL that would let me swap the inner and outer vectors around quickly and efficiently, rather than writing...
for (int iRow = 0; iRow < nRows; ++iRow)
{
for (int iCol = 0; iCol < nCols; ++iCol)
{
myNew2DArray[iCol][iRow] = myOriginal2DArray[iRow][iCol];
}
}
Alternatively, you can store the matrix in a vector and have a flag that specifies whether the matrix is transposed or not. Then you simply calculate the index. Here is an example:
class Matrix {
private:
std::vector<int> matrix;
bool isTransposed = false;
int width, height;
public:
// ...
int getElement(int x, int y)
{
int w = width;
int h = height;
if(isTransposed) {
int z = x;
x = y;
y = x;
z = w;
w = h;
h = z;
}
return matrix[y * width + x];
}
// ...
};
This will reduce the cost of transposing the matrix, but increases the cost of actually accessing the elements.
My suggestion would be to make a class called Matrix that contains the matrix that you are talking about. Give the class a function transpose() that toggles a state flag for the state "transposed". Then, overload the [] operator to follow mwd's suggestion of inverting the indeces when the matrix is in the transposed state.
What you've coded already is pretty much the easiest way. Really you don't need a vector of vectors. You can just append each new 'row' to a single vector. Then what would have been element matrix[i][j] in your original vector of vectors is now matrix[(i*n)+j], when n is the 'width' of your matrix. The fiddly part is coming up with the algorithm to perform the transpose. I'm not saying this way is any better, but it's an alternative route, and what you've got already is fine.
Your best bet is using the Eigen matrix library, which stores the transposedness property in a parameter of the matrix class. If that is not an option, google for one of the numerous matrix transpose algorithms.