Assume that I have a vector:
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
What I need to do is split this vector into block sizes of blocksize with an overlap
blocksize = 4
overlap = 2
The result, would be a 2D vector with size 4 containing 6 values.
x[0] = [1, 3, 5, 7, 9, 11]
x[1] = [ 2 4 6 8 10 12]
....
I have tried to implement this with the following functions:
std::vector<std::vector<double> > stride_windows(std::vector<double> &data, std::size_t
NFFT, std::size_t overlap)
{
std::vector<std::vector<double> > blocks(NFFT);
for(unsigned i=0; (i < data.size()); i++)
{
blocks[i].resize(NFFT+overlap);
for(unsigned j=0; (j < blocks[i].size()); j++)
{
std::cout << data[i*overlap+j] << std::endl;
}
}
}
This is wrong, and, segments.
std::vector<std::vector<double> > frame(std::vector<double> &signal, int N, int M)
{
unsigned int n = signal.size();
unsigned int num_blocks = n / N;
unsigned int maxblockstart = n - N;
unsigned int lastblockstart = maxblockstart - (maxblockstart % M);
unsigned int numbblocks = (lastblockstart)/M + 1;
std::vector<std::vector<double> > blocked(numbblocks);
for(unsigned i=0; (i < numbblocks); i++)
{
blocked[i].resize(N);
for(int j=0; (j < N); j++)
{
blocked[i][j] = signal[i*M+j];
}
}
return blocked;
}
I wrote this function, thinking that it did the above, however, it will just store:
X[0] = 1, 2, 3, 4
x[1] = 3, 4, 5, 6
.....
Could anyone please explain how I would go about modifying the above function to allow for skips by overlap to take place?
This function is similar to this: Rolling window
EDIT:
I have the following vector:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
I want to split this vector, into sub-blocks (thus creating a 2D vector), with an overlap of the parameter overlap so in this case, the parameters would be: size=4 overlap=2, this would then create the following 2D vector:
`block0 = [ 1 3 5 7 9 11]
block1 = [ 2 4 6 8 10 12]
block2 = [ 3 5 7 9 11 13]
block3 = [ 4 6 8 10 12 14]`
So essentially, 4 blocks have been created, each block contains a value where the element is skipped by the overlap
EDIT 2:
This is where I need to get to:
The value of overlap will overlap the results of x in terms of placements inside the vector:
block1 = [1, 3, 5, 7, 9, 11]
Notice from the actual vector block:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
Value: 1 -> This is pushed into block "1"
Value 2 -> This is not pushed into block "1" (overlap is skip 2 places in the vector)
Value 3 -> This is pushed into block "1"
value 4 -> This is not pushed into block "1" (overlap is skip to places in the vector)
value 5 -> This is pushed into block "1"
value 6 -> "This is not pushed into block "1" (overlap is skip 2 places in the vector)
value 7 -> "This value is pushed into block "1"
value 8 -> "This is not pushed into block "1" (overlap is skip 2 places in the vector)"
value 9 -> "This value is pushed into block "1"
value 10 -> This value is not pushed into block "1" (overlap is skip 2 places in the
vector)
value 11 -> This value is pushed into block "1"
BLOCK 2
Overlap = 2;
value 2 - > Pushed back into block "2"
value 4 -> Pushed back into block "2"
value 6, 8, 10 etc..
So each time, the place in the vector is skipped by the "overlap" in this case, it is the value of 2..
This is what the expected output would be:
[[ 1 3 5 7 9 11]
[ 2 4 6 8 10 12]
[ 3 5 7 9 11 13]
[ 4 6 8 10 12 14]]
If I understand you correctly, you're pretty close. You need something like the following. I used int because frankly its easier to type than double =P
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits>
#include <iterator>
std::vector<std::vector<int>>
split(const std::vector<int>& data, size_t blocksize, size_t overlap)
{
// compute maximum block size
std::vector<std::vector<int>> res;
size_t minlen = (data.size() - blocksize)/overlap + 1;
auto start = data.begin();
for (size_t i=0; i<blocksize; ++i)
{
res.emplace_back(std::vector<int>());
std::vector<int>& block = res.back();
auto it = start++;
for (size_t j=0; j<minlen; ++j)
{
block.push_back(*it);
std::advance(it,overlap);
}
}
return res;
}
int main()
{
std::vector<int> data { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
for (size_t i=2; i<6; ++i)
{
for (size_t j=2; j<6; ++j)
{
std::vector<std::vector<int>> blocks = split(data, i, j);
std::cout << "Blocksize = " << i << ", Overlap = " << j << std::endl;
for (auto const& obj : blocks)
{
std::copy(obj.begin(), obj.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
std::cout << std::endl;
}
}
return 0;
}
Output
Blocksize = 2, Overlap = 2
1 3 5 7 9 11 13
2 4 6 8 10 12 14
Blocksize = 2, Overlap = 3
1 4 7 10 13
2 5 8 11 14
Blocksize = 2, Overlap = 4
1 5 9 13
2 6 10 14
Blocksize = 2, Overlap = 5
1 6 11
2 7 12
Blocksize = 3, Overlap = 2
1 3 5 7 9 11
2 4 6 8 10 12
3 5 7 9 11 13
Blocksize = 3, Overlap = 3
1 4 7 10
2 5 8 11
3 6 9 12
Blocksize = 3, Overlap = 4
1 5 9
2 6 10
3 7 11
Blocksize = 3, Overlap = 5
1 6 11
2 7 12
3 8 13
Blocksize = 4, Overlap = 2
1 3 5 7 9 11
2 4 6 8 10 12
3 5 7 9 11 13
4 6 8 10 12 14
Blocksize = 4, Overlap = 3
1 4 7 10
2 5 8 11
3 6 9 12
4 7 10 13
Blocksize = 4, Overlap = 4
1 5 9
2 6 10
3 7 11
4 8 12
Blocksize = 4, Overlap = 5
1 6 11
2 7 12
3 8 13
4 9 14
Blocksize = 5, Overlap = 2
1 3 5 7 9
2 4 6 8 10
3 5 7 9 11
4 6 8 10 12
5 7 9 11 13
Blocksize = 5, Overlap = 3
1 4 7 10
2 5 8 11
3 6 9 12
4 7 10 13
5 8 11 14
Blocksize = 5, Overlap = 4
1 5 9
2 6 10
3 7 11
4 8 12
5 9 13
Blocksize = 5, Overlap = 5
1 6
2 7
3 8
4 9
5 10
Related
I need to sort a std::vector by index. Let me explain it with an example:
Imagine I have a std::vector of 12 positions (but can be 18 for example) filled with some values (it doesn't have to be sorted):
Vector Index: 0 1 2 3 4 5 6 7 8 9 10 11
Vector Values: 3 0 2 3 2 0 1 2 2 4 5 3
I want to sort it every 3 index. This means: the first 3 [0-2] stay, then I need to have [6-8] and then the others. So it will end up like this (new index 3 has the value of previous idx 6):
Vector Index: 0 1 2 3 4 5 6 7 8 9 10 11
Vector Values: 3 0 2 1 2 2 3 2 0 4 5 3
I'm trying to make it in one line using std::sort + lambda but I can't get it. Also discovered the std::partition() function and tried to use it but the result was really bad hehe
Found also this similar question which orders by odd and even index but can't figure out how to make it in my case or even if it is possible: Sort vector by even and odd index
Thank you so much!
Note 0: No, my vector is not always sorted. It was just an example. I've changed the values
Note 1: I know it sound strange... think it like hte vecotr positions are like: yes yes yes no no no yes yes yes no no no yes yes yes... so the 'yes' positions will go in the same order but before the 'no' positions
Note 2: If there isn't a way with lambda then I thought making it with a loop and auxiliar vars but it's more ugly I think.
Note 3: Another example:
Vector Index: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Vector Values: 3 0 2 3 2 0 1 2 2 4 5 3 2 3 0 0 2 1
Sorted Values: 3 0 2 1 2 2 2 3 0 3 2 0 4 5 3 0 2 1
The final Vector Values is sorted (in term of old index): 0 1 2 6 7 8 12 13 14 3 4 5 9 10 11 15 16 17
You can imagine those index in 2 colums, so I want first the Left ones and then the Right one:
0 1 2 3 4 5
6 7 8 9 10 11
12 13 14 15 16 17
You don't want std::sort, you want std::rotate.
std::vector<int> v = {20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31};
auto b = std::next(std::begin(v), 3); // skip first three elements
auto const re = std::end(v); // keep track of the actual end
auto e = std::next(b, 6); // the end of our current block
while(e < re) {
auto mid = std::next(b, 3);
std::rotate(b, mid, e);
b = e;
std::advance(e, 6);
}
// print the results
std::copy(std::begin(v), std::end(v), std::ostream_iterator<int>(std::cout, " "));
This code assumes you always do two groups of 3 for each rotation, but you could obviously work with whichever arbitrary ranges you wanted.
The output looks like what you'd want:
20 21 22 26 27 28 23 24 25 29 30 31
Update: #Blastfurnace pointed out that std::swap_ranges would work as well. The rotate call can be replaced with the following line:
std::swap_ranges(b, mid, mid); // passing mid twice on purpose
With the range-v3 library, you can write this quite conveniently, and it's very readable. Assuming your original vector is called input:
namespace rs = ranges;
namespace rv = ranges::views;
// input [3, 0, 2, 3, 2, 0, 1, 2, 2, 4, 5, 3, 2, 3, 0, 0, 2, 1]
auto by_3s = input | rv::chunk(3); // [[3, 0, 2], [3, 2, 0], [1, 2, 2], [4, 5, 3], [2, 3, 0], [0, 2, 1]]
auto result = rv::concat(by_3s | rv::stride(2), // [[3, 0, 2], [1, 2, 2], [2, 3, 0]]
by_3s | rv::drop(1) | rv::stride(2)) // [[3, 2, 0], [4, 5, 3], [0, 2, 1]]
| rv::join
| rs::to<std::vector<int>>; // [3, 0, 2, 1, 2, 2, 2, 3, 0, 3, 2, 0, 4, 5, 3, 0, 2, 1]
Here's a demo.
Problem Explanation
Edit: Solution is added to the bottom in case anyone needs it
Let's Say I have a matrix with following data
1 3 2 1 7 9 5 8
9 1 3 8 6 9 4 1
3 2 4 0 4 5 7 4
3 5 6 4 6 5 7 4
I want to define a size_of_chunks variable that will store the number of chunks for example if I set size_of_chunks=2 then the matrix will become
Chunk1 | Chunk2 | Chunk3 | Chunk4
-------|---------|--------|-------
1 3 | 2 1 | 7 9 | 5 8
9 1 | 3 8 | 6 9 | 4 1
3 2 | 4 0 | 4 5 | 7 4
3 5 | 6 4 | 6 5 | 7 4
I want to take one of these chunks and use push_back to a std::vector<int>temp(row*col);
Chunk1 |
---------|
Start-> 1 3 |
9 1 |
3 2 |
End-> 3 5 |
so the temp will look like the following:
temp = {1, 3, 9, 1, 3, 2, 3, 5}
Later on when I did the same steps to chunk 2 the temp will look like this:
temp = {1, 3, 9, 1, 3, 2, 3, 5, 2, 1, 3, 8, 4, 0, 6, 4}
Code
int row = 4;
int col = 8;
int size_of_chunk = 2;
std::vector<int> A(row*col);
std::vector<int> temp(row*col);
// Here a Call for the Function to Fill A with Data
for(int r=0;r<row;r++){
for(int c=0;c<col;c+=size_of_chunk){
for(int i=0;i<c;i++){
temp.push_back(A[r*col+i]);
}
}
}
It's giving me values that doesn't match to end results how should I approach this problem ?
Thank you!
Solution
for(int c=0;c<col;c+=size_of_chunk){
for(int r=0;r<row;r++){
for(int i=0;i<size_of_chunk;i++){
temp.push_back(A[r*col+i+c]);
}
}
}
Don't specify a size for the vector in the constructor and use push_back, because that way you end up with a vector twice as big as it should be. Do one or the other.
In this case presumably it should be
std::vector<int> temp;
That is, start the vector at size zero and increase it's size using push_back.
I'm trying to read an array in c++, filled with values from 0 to 5, For an unimportant reason, I need to count how many numbers 1, numbers 2, numbers 3, numbers 4 and numbers 5 do stand on the 'iii*DAYS'th position, so when iii = 0 and DAYS is 5, I need to know how many numbers 1, numbers 2, numbers 3, numbers 4 and numbers 5 are located on the 0th, 4th, 9th, 14th position. The code I posted does this quite well, but sometimes, gives a very big unlogical value, -36589245 or 99653256, can somebody tell me why this happens ( it does happen +- one in a hunderd times )
DAYS = 28
NURSES = 33
SHIFTS =5
int calculate_penalty_coverage_offspring(int offspring[NURSES*DAYS])
{
int temporary[DAYS];
int count[DAYS][SHIFTS];
penalty_score_offspring_coverage =0;
for (int ii = 0; ii<DAYS; ii++)
{
int een = 0;
int twee = 0;
int drie = 0;
int vier = 0;
int vijf = 0;
for (int iii = 0; iii<NURSES; iii++)
{
temporary[iii] = offspring[(ii+(iii*DAYS))];
}
for(int a = 0 ; a<DAYS ; a++)
{
if(temporary[a]== 1)
{
een++;
count[ii][0] = een;
}
else if(temporary[a] == 2)
{
twee++;
count[ii][1] = twee;
}
else if(temporary[a]== 3)
{
drie++;
count[ii][2] = drie;
}
else if(temporary[a]== 4)
{
vier++;
count[ii][3] = vier;
}
else if(temporary[a] == 5)
{
vijf++;
count[ii][4] = vijf;
}
}
}
for(int ii = 0; ii<DAYS ; ii++)
{
for (int iii =0 ; iii<SHIFTS ; iii++)
{
cout << count[ii][iii] << '\t';
}
cout << '\n';
}
this is the exeptional output where I talked about, as you can see, there is an onlogical value in the output of -31427696 ... I can't see why the function is working good, except for this one time.
1 2 2 4 4
5 2 2 9 5
9 6 3 5 2
8 3 4 3 8
9 3 3 4 6
5 5 6 8 1
6 8 2 2 5
3 5 8 -31427696 7
5 5 2 5 8
5 7 8 2 3
2 7 1 2 10
5 6 3 5 5
4 4 4 6 7
7 4 6 4 6
6 5 6 4 3
5 3 7 4 6
5 5 6 1 7
5 5 1 6 2
4 6 6 4 5
3 3 4 5 9
6 6 5 4 4
5 5 4 4 5
8 4 4 5 3
5 5 4 7 5
4 8 6 3 3
9 1 5 7 3
3 7 5 2 5
2 6 5 7 5
First you say
int temporary[DAYS];
Where
DAYS = 28
Then you do:
for (int iii = 0; iii<NURSES; iii++)
{
temporary[iii] = offspring[(ii+(iii*DAYS))];
}
Where
NURSES = 33
You're trying to access indices that are out of bounds in temporary.
EDIT: Following our discussion in the comments,
You're additionally not initializing your arrays, specifically count:
int count[DAYS][SHIFTS];
Which you then conditionally fill in (partially) later:
if(temporary[a]== 1)
{
een++;
count[ii][0] = een;
}
// ...
Accesses to count afterwards to indices that were not assigned to will result in the garbage numbers you're seeing. You should probably just default the matrix to all zeros like so:
int count[DAYS][SHIFTS] = {0};
I'm trying to use the MKL routine mkl_dcsradd to add an upper-triangular matrix to its transpose. In this case, the upper triangular matrix stores part of the adjacency matrix of a graph, and I need the full version for implementing another algorithm.
In this simplified example, I start with a list of (11) edges, and build an upper-triangular CSR matrix from it. I have checked that this much works. However, when I try to add it to its transpose, dcsradd stops on the final row, saying it's run out of space. However, this shouldn't be the case. An upper triangular matrix (no zeros along the diagonal) with n non-zero entries, when added to its transpose, should result in a matrix with 2n (22) non-zeros.
When I supply dcsradd with a maximum non-zeros of 22, it fails, but when I supply it with 23 (an excessive value), it works correctly. Why is this?
I've simplified my code down to a minimal example demonstrating the error:
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <mkl.h>
int main()
{
int nnz = 11;
int numVertices = 10;
int32_t u[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1 };
int32_t v[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 5, 8 };
double w[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
int fullNnz = nnz * 2;
int dim = numVertices;
double triData[nnz];
int triCols[nnz];
int triRows[dim];
// COO to upper-triangular CSR
int info = -1;
int job [] = { 2, 1, 0, 0, nnz, 0 };
mkl_dcsrcoo(job, &dim,
triData, triCols, triRows,
&nnz, w, u, v,
&info);
printf("info = %d\n", info);
// Allocate final memory
double data[fullNnz];
int cols[fullNnz];
int rows[dim];
// B = A + A^T (to make a full adjacency matrix)
int request = 0, sort = 0;
double beta = 1.0;
int WRONG_NNZ = fullNnz + 1; // What is happening here?
mkl_dcsradd("t", &request, &sort, &dim, &dim,
triData, triCols, triRows,
&beta, triData, triCols, triRows,
data, cols, rows,
&WRONG_NNZ, &info);
printf("info = %d\n", info);
// Convert back to 0-based indexing (via Cilk)
cols[:]--;
rows[:]--;
printf("data:");
for (double d : data) printf("%.0f ", d);
printf("\ncols:");
for (int c : cols) printf("%d ", c);
printf("\nrows:");
for (int r : rows) printf("%d ", r);
printf("\n");
return 0;
}
I compile with:
icc -O3 -std=c++11 -xHost main.cpp -o main -openmp -L/opt/intel/composerxe/mkl/lib -lmkl_intel_lp64 -lmkl_core -lmkl_intel_thread -lpthread -lm
When I give 22, the output is:
info = 0
info = 10
data:1 10 1 2 11 2 3 3 4 4 5 10 5 6 6 7 7 8 11 8 9 0
cols:1 5 0 2 8 1 3 2 4 3 5 0 4 6 5 7 6 8 1 7 9 -1
rows:0 2 5 7 9 11 14 16 18 21
But, when I give 23, the output is:
info = 0
info = 0
data:1 10 1 2 11 2 3 3 4 4 5 10 5 6 6 7 7 8 11 8 9 9
cols:1 5 0 2 8 1 3 2 4 3 5 0 4 6 5 7 6 8 1 7 9 8
rows:0 2 5 7 9 11 14 16 18 21
I have for example the following matrix B which is stored in COO and CSR format (retrieved from the non-symetric example here). Could you please suggest an efficient c++ way to apply the matlab sum(B,2) function using the coo or csr(or both) storing format? Because it is quit possible to work with large arrays can we do that using parallel programming (omp or CUDA (e.g, thrust))?
Any algorithmic or library based suggestions are highly appreciated.
Thank you!
PS: Code to construct a sparse matrix and get the CSR coordinates can be found for example in the answer of this post.
COO format: CSR format:
row_index col_index value columns row_index value
1 1 1 0 0 1
1 2 -1 1 3 -1
1 3 -3 3 5 -3
2 1 -2 0 8 -2
2 2 5 1 11 5
3 3 4 2 13 4
3 4 6 3 6
3 5 4 4 4
4 1 -4 0 -4
4 3 2 2 2
4 4 7 3 7
5 2 8 1 8
5 5 -5 4 -5
For COO its pretty simple:
struct MatrixEntry {
size_t row;
size_t col;
int value;
};
std::vector<MatrixEntry> matrix = {
{ 1, 1, 1 },
{ 1, 2, -1 },
{ 1, 3, -3 },
{ 2, 1, -2 },
{ 2, 2, 5 },
{ 3, 3, 4 },
{ 3, 4, 6 },
{ 3, 5, 4 },
{ 4, 1, -4 },
{ 4, 3, 2 },
{ 4, 4, 7 },
{ 5, 2, 8 },
{ 5, 5, -5 },
};
std::vector<int> sum(5);
for (const auto& e : matrix) {
sum[e.row-1] += e.value;
}
and for large matrixes you can just split up the for loop into multiple smaller ranges and add the results at the end.
If you only need the sum of each row (and not columwise) CSR is also straight forward (and even more efficient):
std::vector<int> row_idx = { 0, 3, 5, 8, 11, 13 };
std::vector<int> value = { 1, -1, -3, -2, 5, 4, 6, 4, -4, 2, 7, 8, -5 };
std::vector<int> sum(5);
for(size_t i = 0; i < row_idx.size()-1; ++i) {
sum[i] = std::accumulate(value.begin() + row_idx[i], value.begin() + row_idx[i + 1], 0);
}
Again, for parallelism you can simply split up the loop.