I have a column-based(each column is a feature) large array(around 100M) which has dimensions of 75000(fixed)*number of samples
This is data vector:
std::vector<float> features;
I have used this code to calculate mean:
cv::Mat data(FEATURE_SIZE, features.size()/FEATURE_SIZE, CV_32F, &features[0]);
cv::reduce(data,dataMeans,1,CV_REDUCE_AVG);
FEATURE_SIZE is 75000 and features is a float vector which has all the data.
In order to calculate mean shift I used this:
data -= cv::repeat(dataMeans,1,features.size()/FEATURE_SIZE);
Which I think tries to create an array of same size with my features array and therefore giving me a bad allocation exception.
I just need that array to be mean differentiated. Is there any way to do it without copying, on the same memory location?
First, you messed up columns and rows.
Here a correct way to do what you want:
#define FEATURES_SIZE 3
int main()
{
vector<float> features = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
Mat1f data(features.size() / FEATURES_SIZE, FEATURES_SIZE, &features[0]);
Mat dataMeans;
cv::reduce(data, dataMeans, 1, CV_REDUCE_AVG);
data -= repeat(dataMeans, 1, FEATURES_SIZE);
}
However, probably you can't use opencv matrices with your dimensions.
You can instead use std functions:
// other includes
#include <algorithm>
#include <numeric>
#include <functional>
#define FEATURES_SIZE 3
int main()
{
vector<float> features = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
for(size_t i = 0; i<features.size(); i+= FEATURES_SIZE)
{
float cumsum = accumulate(features.begin() + i, features.begin() + i + FEATURES_SIZE, 0.f);
float avg = cumsum / FEATURES_SIZE;
transform(features.begin() + i, features.begin() + i + FEATURES_SIZE, features.begin() + i, bind2nd(std::minus<float>(), avg));
}
}
I don't know if this is the "minimum number of copies" optimal solution. Try with your large arrays and check if it is a problem.
Note: using namespace std; and using namespace cv used in my examples for brevity.
Hope it helps!
Related
I have some vector vec and i want to obtain a new "expression" vec2 by copying values along dimension of vector
Eigen::VectorXf vec(5);
vec << 1, 2, 3, 4, 5;
const auto vec2 = vec.someAwesomeEigenMagic<3>();
//vec2 should contains (1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5)^T
//Not (1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5)^T
Of course i can create such vector manually or by using replicate + vectorization by Eigen::Map:
MatrixXf tmp = vec.replicate(1, 3).transpose();
const Map<VectorXf> vec2(tmp.data(), vec.rows() * 3, 1);
But i want vec2 to be some kind of "eigen template expression" without allication (vec can be quite big and i will call this routine quite often) and immediate computing of values. (vec contains per vertex weights and i want to use it for weighted least squares)
I thought about kronecker product trick with vector of ones, but i'm not sure is it optimized for product by ones. Also i prefer to avoid unsupported module
PS Sorry for my English
Using the devel branch you can use LinSpaced to generate the sequence of indices and then index the input vector:
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
VectorXf vec(5);
vec << 1, 2, 3, 4, 5;
auto vecrep = vec(ArrayXi::LinSpaced(5*3,0,4));
cout << vecrep.transpose() << endl;
}
you can then wrap the key line within a free function returning auto, in c++14:
template<typename XprType>
auto magic_rep(const XprType &xpr, Index K) {
return xpr(Eigen::ArrayXi::LinSpaced(xpr.size()*K,0,xpr.size()-1));
}
and in main:
cout << magic_rep(vec,3).transpose() << endl;
I have a vector that allows for duplicates, I want to randomly chose an element with the probability that represents how many times an element was repeated.
For example - for the vector below, 6 should have the highest probability of being chosen. I thought about using rand(), but I am not quiet sure how to incorporate the probability.
vector A = [ 0, 0, 2, 2, 4, 5, 1, 6, 6, 6]
thanks
I think you are on the right way for getting a custom distribution of values. See the following code which demonstrates the access to the vector. Hope it helps.
#include <cstdlib>
#include <iostream>
#include <ctime>
#include <vector>
int main()
{
std::vector<int> A { 0, 0, 2, 2, 4, 5, 1, 6, 6, 6 };
std::srand(std::time(0)); // use current time as seed for random generator
int random_pos = std::rand() % A.size(); // Modulo to restrict the number of random values to be at most A.size()-1
int random_val = A[random_pos];
}
Maybe something like this (untested!):
#include <vector>
#include <random>
#include <iostream>
int main()
{
std::vector<size_t> A{0, 0, 2, 2, 4, 5, 1, 6, 6, 6};
static thread_local std::mt19937 g{std::random_device{}()};
static thread_local std::uniform_int_distribution<size_t> d{0,A.size()};
std::cout << A[d(g)] << std::endl;
}
I've got a C-style array called board that contains some char's. I'm trying to create a std::array or std::vector (either would be fine, although std::array would be preferable) to store all the indices of board that are a certain value (in my case, 0).
This code I wrote is functional and works well:
std::vector<int> zeroes;
zeroes.reserve(16);
//board has 16 elements, so zeroes.size() will never be larger than 16.
//I used this reserve for speedup - the compiler doesn't require it.
for (int i = 0; i < 16; ++i)
{
if (board[i] == 0)
{
zeroes.push_back(i);
}
}
However, from past experience, whenever a std function exists that could replace part of my code, it is terser and hence stylistically preferred and also faster. My function seems like a fairly basic operation - I know there is a standard function* to access the index of an array that contains a value when that value only occurs once** in the array. So, is there a standard function to create an array of the indices that contain a value, assuming that more than one such index exists?
* Technically, two nested function calls: int x = std::distance(board, std::find(board, board + 16, 0));. See the accepted answer here.
** Well, it still works if more than one index with the desired value is present, but it returns only the first such index, which isn't very useful in my context.
Edit:
As one of the answers misunderstood the question, I'll clarify what I'm seeking. Let's say we have:
char board[16] = {0, 2, 0, 4,
2, 4, 8, 2,
0, 0, 8, 4,
2, 0, 0, 2};
Now, the indices which I'm looking for are {0, 2, 8, 9, 13, 14} because board[0] = 0, board[2] = 0, board[8] = 0, etc. and these are the only numbers which satisfy that property.
Here's a solution using std::iota and std::remove_if:
#include <algorithm>
#include <iostream>
int main () {
const std::size_t board_size = 16;
char board [board_size] = {
0, 2, 0, 4,
2, 4, 8, 2,
0, 0, 8, 4,
2, 0, 0, 2
};
// Initialize a zero-filled vector of the appropriate size.
std::vector<int> zeroes(board_size);
// Fill the vector with index values (0 through board_size - 1).
std::iota(zeroes.begin(), zeroes.end(), 0);
// Remove the index values that do not correspond to zero elements in the board.
zeroes.erase(std::remove_if(zeroes.begin(), zeroes.end(), [&board] (int i) {
return board[i] != 0;
}), zeroes.end());
// Output the resulting contents of the vector.
for (int i : zeroes) {
std::cout << i << std::endl;
}
}
Output of the program (demo):
0
2
8
9
13
14
I have a std::vector of constant size 2n, and its contents - more vectors - are added in this order (cannot be changed):
1, 1+n, 2, 2+n, 3, 3+n, 4, 4+n etc.
For instance, where n=6 the order of adding would be: 1,7,2,8 etc.
Once populated, I would like to reorder the contents of my vector to 1, 2, 3 etc.
Can anyone suggest how I might go about that? I can't help thinking there's some lovely elegant approach that's just beyond my reach.
With a little help from my friends #Boost:
typedef std::vector<int> V;
V const v { 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16 };
auto rearranged = copy_range<V>(join(
v | strided(2),
v | sliced(1, v.size()) | strided(2)));
See it Live At Coliru
#include <boost/range/adaptors.hpp>
#include <boost/range/join.hpp>
#include <boost/range/algorithm.hpp>
using namespace boost::adaptors;
using boost::copy_range;
#include <iostream>
int main() {
typedef std::vector<int> V;
V const v { 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16 };
auto rearranged = copy_range<V>(join(
v | strided(2),
v | sliced(1, v.size()) | strided(2)));
// print the result
boost::copy(rearranged, std::ostream_iterator<int>(std::cout,";"));
}
Prints
1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;
Since the vector is of a constant size 2n, while populating you can change the index accordingly.
index = (i%2) ? i/2+n+1 : i/2+1;
Where i = 0 to 2n-1
When you get the value of n, declare your vector as
std::vector<myType> vec( 2*n );
the function to map from current place to proper place is easy enough.
fn(int x,int n) { (i%2) ? i/2+n+1 : i/2+1; }
Declare a new vector, with default contents. The loop over them doing swaps.
for(i=0,i<size;i++) {swap(v1[i],v2[fn(i,n)]);}
Of course this likely has serious off by one issues, since your description is 1 based, not zero based like vectors.
My question is as follows:
Refer to the following array declaration in the main():
const int size = 4;
int x[size][size] = {{1, 2, 3, 4}, {5, 6, 7, 8},
{9, 8, 7, 3}, {2, 1, 7, 1}};
Write a function SwapRows() to swap two rows of the above 2D array. For
example, if the function has been called to swap the first and the second rows of the
above 2D array then the result would be that the first row now becomes {5, 6, 7, 8}
and the second row now becomes {1, 2, 3, 4}. The function receives as parameter the
2D array, the size of the array, and two integers to indicate the rows to swap.
Help,,how can i go about this?????
Note: Using C++ Language
Pseudo code:
SwapRows(x[size][size], row0, row1, size)
for col = 0 to size - 1 do
temp = x[row0][col]
x[row0][col] = x[row1][col]
x[row1][col] = temp
Now all you need to do is convert the pseudo code into C++, then test, debug and document it.
#include <algorithm>
void SwapRows(int arr[][4], int r1, int r2)
{
std::swap(arr[r1],arr[r2]);
}