Very simple question: is there a smart way of creating a subvector from regularly spaced elements of another vector with the STL?
In short, is it possible to write the following code with a STL algorithm:
int inc = 2;
std::vector<double> v_origin;
std::vector<double> v_dest;
for (int i = 0; i < v_origin.size(); i+= inc)
v_dest.push_back(v_origin[i]);
Like I would write in Matlab or Python something like:
v_dest = v_origin[0:inc:end];
As a general solution, you could define a stride iterator. If you use Boost.Range, then it already as a strided range adaptor.
Example:
#include <vector>
#include <iostream>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
int main()
{
int inc = 2;
std::vector<double> v_origin;
std::vector<double> v_dest;
for (int i = 0; i < 10; ++ i)
v_origin.push_back(i);
boost::copy(v_origin | boost::adaptors::strided(2),
std::back_inserter(v_dest));
// ^ In Python: v_dest[] = v_origin[::2]
boost::copy(v_dest, std::ostream_iterator<double>(std::cout, ", "));
}
(Creating another answer as it's a different approach.)
If you just want to push_back a strided slice of another container, and does not intend to use that lst[a:b:c] concept anywhere else, it is probably easier to write a generic copy-like function:
template <typename InputIterator, typename OutputIterator>
void copy_strided(InputIterator begin, InputIterator end,
OutputIterator result, size_t stride)
{
assert(stride >= 1);
for (size_t i = stride; begin != end; ++ i, ++ begin)
{
if (i == stride)
{
*result = *begin;
++ result;
i = 0;
}
}
}
Usage:
#include <vector>
#include <cassert>
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
int inc = 2;
std::vector<double> v_origin;
std::vector<double> v_dest;
for (int i = 0; i < 10; ++ i)
v_origin.push_back(i);
copy_strided(v_origin.begin(), v_origin.end(), std::back_inserter(v_dest), inc);
std::copy(v_dest.begin(), v_dest.end(), std::ostream_iterator<double>(std::cout, ", "));
}
struct RemoveNth
{
RemoveNth(int incin)
{
count = 0;
inc = incin;
}
bool operator()(double x )
{
return count++ % inc == 0;
}
int count;
int inc;
};
int main()
{
int inc = 2;
std::vector<double> v_origin;
std::vector<double> v_dest;
for ( int i = 0 ; i < 100; ++i )
v_origin.push_back( i );
v_dest = v_origin;
RemoveNth helper(3);
std::vector<double>::iterator newend =
std::remove_if (v_dest.begin() , v_dest.end(), helper);
v_dest.erase( newend , v_dest.end() );
return 0;
}
Something like above might work.
In C++11 you can use std::copy_if and instead of the separate functor you can use inline lambdas like so
template<typename T, typename U>
void copynth( T begin , T end , U dest , int n )
{
int count = 0;
std::copy_if( begin , end , dest ,
[&count,n]( double x )
{
return count++ % n == 0;
});
}
int main()
{
int inc = 2;
std::vector<double> v_origin;
std::vector<double> v_dest;
for ( int i = 0 ; i < 100; ++i )
v_origin.push_back( i );
int count = 0;
copynth( v_origin.begin() , v_origin.end() , std::back_inserter(v_dest) , 4);
return 0;
}
There does not exist anything in the standard library that is meant for this task specifically.
Below is my own generic implementation. There is a separate implementation for random access iterator and for other input iterators.
#include <iterator>
namespace detail {
template <class SourceIter, class OutIter>
void strided_copy_aux(SourceIter from, SourceIter to, OutIter out, unsigned step, std::random_access_iterator_tag)
{
SourceIter end = (to - from) / step * step + from;
for (; from < end; from += step ) {
*out = *from;
}
if (end < to) {
*out = *end;
}
}
template <class SourceIter, class OutIter>
void strided_copy_aux(SourceIter from, SourceIter to, OutIter out, unsigned step, std::input_iterator_tag)
{
while (from != to) {
*out = *from;
for (unsigned i = 0; i != step; ++i) {
++from;
if (from == to) break;
}
}
}
}
template <class SourceIter, class OutIter>
void strided_copy(SourceIter from, SourceIter to, OutIter out, unsigned step)
{
detail::strided_copy_aux(from, to, out, step, typename std::iterator_traits<SourceIter>::iterator_category());
}
Usage example: http://ideone.com/1Wmq3
Related
I'm trying to return indexes of lowest values in an array, and i'm unable to find a good solution anywhere.
int indexofSmallestElement(double array[], int size)
{
int index = 0;
for(int i = 1; i < size; i++)
{
if(array[i] < array[index])
index = i;
}
return index;
}
This is the probably the simplest way of finding index of one value, but what if I have multiple lowest values in an array?
EDIT: Oh, I just realized from the comment that there is the possibility of duplicate values, so if the question is actually that, you could do this, it also returning a std::vector:
std::vector<int> indexesOfSmallestElements(double array[], int size)
{
std::vector<int> indexes = { 0 };
for (int i = 1; i < size; i++)
{
double current_smallest = array[indexes.front()];
if (array[i] < current_smallest) {
indexes.clear();
indexes.emplace_back(i);
}
else if (array[i] == current_smallest) {
indexes.emplace_back(i);
}
}
return indexes;
}
ORIGINAL:
"Lowest" is always only one, if you want "lower than a value", just return a std::vector.
std::vector<int> indexesOfSmallElements(double array[], int size, double value)
{
std::vector<int> indexes;
for (int i = 0; i < size; i++)
{
if (array[i] < value) {
indexes.emplace_back(i);
}
}
return indexes;
}
Array indices are a fairly inflexible concept, in C++ you can gain plenty of generality with iterators - there's a whole lot of C++ algorithms that take iterators directly, and essentially next to nothing in the standard library uses naked indices.
C++20 & onwards
We can create a minimums range view (lazy range combinator) that takes a range, and returns a range that only contains the minimums from the original range. The range isn't a new vector with filtered elements: it is a view onto the original range (e.g. onto the original vector of doubles).
#include <algorithm>
#include <ranges>
#include <vector>
template <typename Range>
auto minimums(Range && range) {
using namespace std::ranges;
auto first_min = min_element(range);
auto const is_min = [=](auto const &el){ return el == *first_min; };
return subrange(first_min, std::end(range)) | views::filter(is_min);
}
You definitely do not need to recover the indices of the array - iterators are a generic concept and apply quite widely. But just to show a solution equivalent to the one for C++17 & prior below, let's write some adapters that'll help with index recovery:
template <typename Range>
auto addressof(Range && range) {
using namespace std::ranges;
return views::transform(range, [](auto &el){ return ⪙ });
}
template <typename Range, typename It>
auto array_indices(Range && range, It && reference) {
using namespace std::ranges;
auto to_index = [ref_addr = &*reference](auto *el){ return ref_addr - el; };
return range | addressof | views::transform(to_index);
}
And now we can test it:
#include <cassert>
#include <iostream>
int main()
{
const double array[] = {8, 3, -1, -1, 9, -1, 5};
auto min_range = minimums(array);
{ // test
auto min = std::ranges::min_element(array);
// have we got the correct number of minimums?
auto min_size = std::distance(std::begin(min_range), std::end(min_range));
assert(min_size == std::count(std::begin(array), std::end(array), *min));
// are all of the minimums indeed minimums?
assert(std::ranges::all_of(min_range,
[=](auto &el){ return el == *min; }));
// are all of the minimums references to the array
assert(std::ranges::all_of(min_range,
[&](auto &el){ return &el >= std::begin(array) && &el < std::end(array); }));
}
for (auto &min : min_range)
std::cout << std::distance(std::begin(array), &min) << ' ';
std::cout << '\n';
}
Output:
2 3 5
C++17 through C++11
Thus, let's have a minimumLocations function that takes two forward iterators that define a range, and return a vector of iterators to all the minimums that were found:
#include <iterator>
#include <type_traits>
#include <vector>
template <typename I1, typename I2>
std::vector<I1> minimumLocations(I1 start, I2 end)
{
if (start == end) return {};
std::vector<I1> locations = {start};
std::decay<decltype(*start)>::type min = *start;
std::advance(start, 1);
for (; start != end; std::advance(start, 1)) {
auto const &value = *start;
if (value < min) {
// new minimum
locations.clear();
locations.push_back(start);
min = *start;
}
else if (value == min)
locations.push_back(start);
}
return locations;
}
For convenience's sake, we can also have an adapter function that takes a range instead of a pair of iterators. In C++, a "range" is anything that has a beginning and an end:
template <typename R>
auto minimumLocations(R &range) {
return minimumLocations(std::begin(range), std::end(range));
}
Both of the functions will work on any container that provides forward iterators - not only on arrays, but also vectors, lists, forward lists, etc. A specialized version could also be provided for pre-sorted containers.
And now a test and a demo:
#include <algorithm>
#include <cassert>
#include <iostream>
int main()
{
const double array[] = {8, 3, -1, -1, 9, -1, 5};
auto min_indices = minimumLocations(array);
{ // test
auto min = std::min_element(std::begin(array), std::end(array));
// have we got the correct numer of locations?
assert(min_indices.size() == std::count(std::begin(array), std::end(array), *min));
// are all of the locations indeed minimums?
assert(std::all_of(std::begin(min_indices), std::end(min_indices),
[=](auto it){ return *it == *min; }));
}
for (auto i : min_indices)
std::cout << std::distance(array, i) << ' ';
std::cout << '\n';
}
Output:
2 3 5
In a program I need to apply a function in parallel to each unique permutation of a vector. The size of the vector is around N=15
I already have a function void parallel_for_each_permutation which I can use in combination with a std::set to only process each unique permutation exactly once.
This all works well for the general case. However, in my use case the number of unique elements k per vector is very limited, usually around k=4. This means that I'm currently wasting time constructing the same unique permutation over and over again, just to throw it away because it has already been processed.
Is it possible to process all unique permutations in this special case, without constructing all N! permutations?
Example use-case:
#include <algorithm>
#include <thread>
#include <vector>
#include <mutex>
#include <numeric>
#include <set>
#include <iostream>
template<class Container1, class Container2>
struct Comp{
//compare element-wise less than
bool operator()(const Container1& l, const Container2& r) const{
auto pair = std::mismatch(l.begin(), l.end(), r.begin());
if(pair.first == l.end() && pair.second == r.end())
return false;
return *(pair.first) < *(pair.second);
}
};
template<class Container, class Func>
void parallel_for_each_permutation(const Container& container, int num_threads, Func func){
auto ithPermutation = [](int n, size_t i) -> std::vector<size_t>{
// https://stackoverflow.com/questions/7918806/finding-n-th-permutation-without-computing-others
std::vector<size_t> fact(n);
std::vector<size_t> perm(n);
fact[0] = 1;
for(int k = 1; k < n; k++)
fact[k] = fact[k-1] * k;
for(int k = 0; k < n; k++){
perm[k] = i / fact[n-1-k];
i = i % fact[n-1-k];
}
for(int k = n-1; k > 0; k--){
for(int j = k-1; j >= 0; j--){
if(perm[j] <= perm[k])
perm[k]++;
}
}
return perm;
};
size_t totalNumPermutations = 1;
for(size_t i = 1; i <= container.size(); i++)
totalNumPermutations *= i;
std::vector<std::thread> threads;
for(int threadId = 0; threadId < num_threads; threadId++){
threads.emplace_back([&, threadId](){
const size_t firstPerm = size_t(float(threadId) * totalNumPermutations / num_threads);
const size_t last_excl = std::min(totalNumPermutations, size_t(float(threadId+1) * totalNumPermutations / num_threads));
Container permutation(container);
auto permIndices = ithPermutation(container.size(), firstPerm);
size_t count = firstPerm;
do{
for(int i = 0; i < int(permIndices.size()); i++){
permutation[i] = container[permIndices[i]];
}
func(threadId, permutation);
std::next_permutation(permIndices.begin(), permIndices.end());
++count;
}while(count < last_excl);
});
}
for(auto& thread : threads)
thread.join();
}
template<class Container, class Func>
void parallel_for_each_unique_permutation(const Container& container, Func func){
using Comparator = Comp<Container, Container>;
constexpr int numThreads = 4;
std::set<Container, Comparator> uniqueProcessedPermutations(Comparator{});
std::mutex m;
parallel_for_each_permutation(
container,
numThreads,
[&](int threadId, const auto& permutation){
{
std::lock_guard<std::mutex> lg(m);
if(uniqueProcessedPermutations.count(permutation) > 0){
return;
}else{
uniqueProcessedPermutations.insert(permutation);
}
}
func(permutation);
}
);
}
int main(){
std::vector<int> vector1{1,1,1,1,2,3,2,2,3,3,1};
auto func = [](const auto& vec){return;};
parallel_for_each_unique_permutation(vector1, func);
}
The permutations you have to work with are known in the field of combinatorics as multiset permutations.
They are described for example on The Combinatorial Object Server
with more detailed explanations in this paper by professor Tadao Takaoka.
You have some related Python code and some C++ code in the FXT open source library.
You might consider adding the "multiset" and "combinatorics" tags to your question.
One possibility is to borrow the (header-only) algorithmic code from the FXT library, which provides a simple generator class for those multiset permutations.
Performance level:
Using the FXT algorithm on a test vector of 15 objects, {1,1,1, 2,2,2, 3,3,3,3, 4,4,4,4,4}, one can generate all associated 12,612,600 "permutations" in less than 2 seconds on a plain vanilla Intel x86-64 machine; this is without diagnostics text I/O and without any attempt at optimization.
The algorithm generates exactly those "permutations" that are required, nothing more. So there is no longer a need to generate all 15! "raw" permutations nor to use mutual exclusion to update a shared data structure for filtering purposes.
An adaptor class for generating the permutations:
I will try below to provide code for an adaptor class, which allows your application to use the FXT algorithm while containing the dependency into a single implementation file. That way, the code will hopefully fit better into your application. Think FXT's ulong type and use of raw pointers, versus std::vector<std::size_t> in your code. Besides, FXT is a very extensive library.
Header file for the "adaptor" class:
// File: MSetPermGen.h
#ifndef MSET_PERM_GEN_H
#define MSET_PERM_GEN_H
#include <iostream>
#include <vector>
class MSetPermGenImpl; // from algorithmic backend
using IntVec = std::vector<int>;
using SizeVec = std::vector<std::size_t>;
// Generator class for multiset permutations:
class MSetPermGen {
public:
MSetPermGen(const IntVec& vec);
std::size_t getCycleLength() const;
bool forward(size_t incr);
bool next();
const SizeVec& getPermIndices() const;
const IntVec& getItems() const;
const IntVec& getItemValues() const;
private:
std::size_t cycleLength_;
MSetPermGenImpl* genImpl_; // implementation generator
IntVec itemValues_; // only once each
IntVec items_; // copy of ctor argument
SizeVec freqs_; // repetition counts
SizeVec state_; // array of indices in 0..n-1
};
#endif
The class constructor takes exactly the argument type provided in your main program. Of course, the key method is next(). You can also move the automaton by several steps at once using the forward(incr)method.
Example client program:
// File: test_main.cpp
#include <cassert>
#include "MSetPermGen.h"
using std::cout;
using std::cerr;
using std::endl;
// utility functions:
std::vector<int> getMSPermutation(const MSetPermGen& mspg)
{
std::vector<int> res;
auto indices = mspg.getPermIndices(); // always between 0 and n-1
auto values = mspg.getItemValues(); // whatever the user put in
std::size_t n = indices.size();
assert( n == items.size() );
res.reserve(n);
for (std::size_t i=0; i < n; i++) {
auto xi = indices[i];
res.push_back(values[xi]);
}
return res;
}
void printPermutation(const std::vector<int>& p, std::ostream& fh)
{
std::size_t n = p.size();
for (size_t i=0; i < n; i++)
fh << p[i] << " ";
fh << '\n';
}
int main(int argc, const char* argv[])
{
std::vector<int> vec0{1,1, 2,2,2}; // N=5
std::vector<int> vec1{1,1, 1,1, 2, 3, 2,2, 3,3, 1}; // N=11
std::vector<int> vec2{1,1,1, 2,2,2, 3,3,3,3, 4,4,4,4,4}; // N=15
MSetPermGen pg0{vec0};
MSetPermGen pg1{vec1};
MSetPermGen pg2{vec2};
auto pg = &pg0; // choice of 0, 1, 2 for sizing
auto cl = pg->getCycleLength();
auto permA = getMSPermutation(*pg);
printPermutation(permA, cout);
for (std::size_t pi=0; pi < (cl-1); pi++) {
pg->next();
auto permB = getMSPermutation(*pg);
printPermutation(permB, cout);
}
return EXIT_SUCCESS;
}
Text output from the above small program:
1 1 2 2 2
1 2 1 2 2
1 2 2 1 2
1 2 2 2 1
2 1 1 2 2
2 1 2 1 2
2 1 2 2 1
2 2 1 1 2
2 2 1 2 1
2 2 2 1 1
You get only 10 items from vector {1,1, 2,2,2}, because 5! / (2! * 3!) = 120/(2*6) = 10.
The implementation file for the adaptor class, MSetPermGen.cpp, consists of two parts. The first part is FXT code with minimal adaptations. The second part is the MSetPermGen class proper.
First part of implementation file:
// File: MSetPermGen.cpp - part 1 of 2 - FXT code
// -------------- Beginning of header-only FXT combinatorics code -----------
// This file is part of the FXT library.
// Copyright (C) 2010, 2012, 2014 Joerg Arndt
// License: GNU General Public License version 3 or later,
// see the file COPYING.txt in the main directory.
//-- https://www.jjj.de/fxt/
//-- https://fossies.org/dox/fxt-2018.07.03/mset-perm-lex_8h_source.html
#include <cstddef>
using ulong = std::size_t;
inline void swap2(ulong& xa, ulong& xb)
{
ulong save_xb = xb;
xb = xa;
xa = save_xb;
}
class mset_perm_lex
// Multiset permutations in lexicographic order, iterative algorithm.
{
public:
ulong k_; // number of different sorts of objects
ulong *r_; // number of elements '0' in r[0], '1' in r[1], ..., 'k-1' in r[k-1]
ulong n_; // number of objects
ulong *ms_; // multiset data in ms[0], ..., ms[n-1], sentinels at [-1] and [-2]
private: // have pointer data
mset_perm_lex(const mset_perm_lex&); // forbidden
mset_perm_lex & operator = (const mset_perm_lex&); // forbidden
public:
explicit mset_perm_lex(const ulong *r, ulong k)
{
k_ = k;
r_ = new ulong[k];
for (ulong j=0; j<k_; ++j) r_[j] = r[j]; // get buckets
n_ = 0;
for (ulong j=0; j<k_; ++j) n_ += r_[j];
ms_ = new ulong[n_+2];
ms_[0] = 0; ms_[1] = 1; // sentinels: ms[0] < ms[1]
ms_ += 2; // nota bene
first();
}
void first()
{
for (ulong j=0, i=0; j<k_; ++j)
for (ulong h=r_[j]; h!=0; --h, ++i)
ms_[i] = j;
}
~mset_perm_lex()
{
ms_ -= 2;
delete [] ms_;
delete [] r_;
}
const ulong * data() const { return ms_; }
ulong next()
// Return position of leftmost change,
// return n with last permutation.
{
// find rightmost pair with ms[i] < ms[i+1]:
const ulong n1 = n_ - 1;
ulong i = n1;
do { --i; } while ( ms_[i] >= ms_[i+1] ); // can read sentinel
if ( (long)i < 0 ) return n_; // last sequence is falling seq.
// find rightmost element ms[j] less than ms[i]:
ulong j = n1;
while ( ms_[i] >= ms_[j] ) { --j; }
swap2(ms_[i], ms_[j]);
// Here the elements ms[i+1], ..., ms[n-1] are a falling sequence.
// Reverse order to the right:
ulong r = n1;
ulong s = i + 1;
while ( r > s ) { swap2(ms_[r], ms_[s]); --r; ++s; }
return i;
}
};
// -------------- End of header-only FXT combinatorics code -----------
Second part of the class implementation file:
// Second part of file MSetPermGen.cpp: non-FXT code
#include <cassert>
#include <tuple>
#include <map>
#include <iostream>
#include <cstdio>
#include "MSetPermGen.h"
using std::cout;
using std::cerr;
using std::endl;
class MSetPermGenImpl { // wrapper class
public:
MSetPermGenImpl(const SizeVec& freqs) : fg(freqs.data(), freqs.size())
{}
private:
mset_perm_lex fg;
friend class MSetPermGen;
};
static std::size_t fact(size_t n)
{
std::size_t f = 1;
for (std::size_t i = 1; i <= n; i++)
f = f*i;
return f;
}
MSetPermGen::MSetPermGen(const IntVec& vec) : items_(vec)
{
std::map<int,int> ma;
for (int i: vec) {
ma[i]++;
}
int item, freq;
for (const auto& p : ma) {
std::tie(item, freq) = p;
itemValues_.push_back(item);
freqs_.push_back(freq);
}
cycleLength_ = fact(items_.size());
for (auto i: freqs_)
cycleLength_ /= fact(i);
// create FXT-level generator:
genImpl_ = new MSetPermGenImpl(freqs_);
for (std::size_t i=0; i < items_.size(); i++)
state_.push_back(genImpl_->fg.ms_[i]);
}
std::size_t MSetPermGen::getCycleLength() const
{
return cycleLength_;
}
bool MSetPermGen::forward(size_t incr)
{
std::size_t n = items_.size();
std::size_t rc = 0;
// move forward state by brute force, could be improved:
for (std::size_t i=0; i < incr; i++)
rc = genImpl_->fg.next();
for (std::size_t j=0; j < n; j++)
state_[j] = genImpl_->fg.ms_[j];
return (rc != n);
}
bool MSetPermGen::next()
{
return forward(1);
}
const SizeVec& MSetPermGen::getPermIndices() const
{
return (this->state_);
}
const IntVec& MSetPermGen::getItems() const
{
return (this->items_);
}
const IntVec& MSetPermGen::getItemValues() const
{
return (this->itemValues_);
}
Adapting the parallel application:
Regarding your multithreaded application, given that generating the "permutations" is cheap, you can afford to create one generator object per thread.
Before launching the actual computation, you forward each generator to its appropriate initial position, that is at step thread_id * (cycleLength / num_threads).
I have tried to adapt your code to this MSetPermGen class along these lines. See code below.
With 3 threads, an input vector {1,1,1, 2,2,2, 3,3,3,3, 4,4,4,4,4} of size 15 (giving 12,612,600 permutations) and all diagnostics enabled, your modified parallel program runs in less than 10 seconds; less than 2 seconds with all diagnostics switched off.
Modified parallel program:
#include <algorithm>
#include <thread>
#include <vector>
#include <atomic>
#include <mutex>
#include <numeric>
#include <set>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include "MSetPermGen.h"
using std::cout;
using std::endl;
// debug and instrumentation:
static std::atomic<size_t> permCounter;
static bool doManagePermCounter = true;
static bool doThreadLogfiles = true;
static bool doLogfileHeaders = true;
template<class Container, class Func>
void parallel_for_each_permutation(const Container& container, int numThreads, Func mfunc) {
MSetPermGen gen0(container);
std::size_t totalNumPermutations = gen0.getCycleLength();
std::size_t permShare = totalNumPermutations / numThreads;
if ((totalNumPermutations % numThreads) != 0)
permShare++;
std::cout << "totalNumPermutations: " << totalNumPermutations << std::endl;
std::vector<std::thread> threads;
for (int threadId = 0; threadId < numThreads; threadId++) {
threads.emplace_back([&, threadId]() {
// generate some per-thread logfile name
std::ostringstream fnss;
fnss << "thrlog_" << threadId << ".txt";
std::string fileName = fnss.str();
std::ofstream fh(fileName);
MSetPermGen thrGen(container);
const std::size_t firstPerm = permShare * threadId;
thrGen.forward(firstPerm);
const std::size_t last_excl = std::min(totalNumPermutations,
(threadId+1) * permShare);
if (doLogfileHeaders) {
fh << "MSG threadId: " << threadId << '\n';
fh << "MSG firstPerm: " << firstPerm << '\n';
fh << "MSG lastExcl : " << last_excl << '\n';
}
Container permutation(container);
auto values = thrGen.getItemValues();
auto permIndices = thrGen.getPermIndices();
auto nsz = permIndices.size();
std::size_t count = firstPerm;
do {
for (std::size_t i = 0; i < nsz; i++) {
permutation[i] = values[permIndices[i]];
}
mfunc(threadId, permutation);
if (doThreadLogfiles) {
for (std::size_t i = 0; i < nsz; i++)
fh << permutation[i] << ' ';
fh << '\n';
}
thrGen.next();
permIndices = thrGen.getPermIndices();
++count;
if (doManagePermCounter) {
permCounter++;
}
} while (count < last_excl);
fh.close();
});
}
for(auto& thread : threads)
thread.join();
}
template<class Container, class Func>
void parallel_for_each_unique_permutation(const Container& container, Func func) {
constexpr int numThreads = 3;
parallel_for_each_permutation(
container,
numThreads,
[&](int threadId, const auto& permutation){
// no longer need any mutual exclusion
func(permutation);
}
);
}
int main()
{
std::vector<int> vector1{1,1,1,1,2,3,2,2,3,3,1}; // N=11
std::vector<int> vector0{1,1, 2,2,2}; // N=5
std::vector<int> vector2{1,1,1, 2,2,2, 3,3,3,3, 4,4,4,4,4}; // N=15
auto func = [](const auto& vec) { return; };
permCounter.store(0);
parallel_for_each_unique_permutation(vector2, func);
auto finalPermCounter = permCounter.load();
cout << "FinalPermCounter = " << finalPermCounter << endl;
}
I have an std::vector of std::function<void()> like this:
std::map<Event, std::vector<std::function<void()>>> observers_;
calling each function like this:
for (const auto& obs : observers_.at(event)) obs();
I want to turn this into a parallel for loop. Since I am using C++14, and don't have access to the std::execution::parallel of C++17, I found a little library that allows me to create a ThreadPool.
How do I turn for (const auto& obs : observers_.at(event)) obs(); into a version that calls each function in observers_ in parallel? I can't seem to get the syntax correct. I tried, but this doesn't work.
std::vector<std::function<void()>> vec = observers_.at(event);
ThreadPool::ParallelFor(0, vec.size(), [&](int i)
{
vec.at(i);
});
The example program that uses the library below:
#include <iostream>
#include <mutex>
#include "ThreadPool.hpp"
////////////////////////////////////////////////////////////////////////////////
int main()
{
std::mutex critical;
ThreadPool::ParallelFor(0, 16, [&] (int i)
{
std::lock_guard<std::mutex> lock(critical);
std::cout << i << std::endl;
});
return 0;
}
The ThreadPool library.
#ifndef THREADPOOL_HPP_INCLUDED
#define THREADPOOL_HPP_INCLUDED
////////////////////////////////////////////////////////////////////////////////
#include <thread>
#include <vector>
#include <cmath>
////////////////////////////////////////////////////////////////////////////////
class ThreadPool {
public:
template<typename Index, typename Callable>
static void ParallelFor(Index start, Index end, Callable func) {
// Estimate number of threads in the pool
const static unsigned nb_threads_hint = std::thread::hardware_concurrency();
const static unsigned nb_threads = (nb_threads_hint == 0u ? 8u : nb_threads_hint);
// Size of a slice for the range functions
Index n = end - start + 1;
Index slice = (Index) std::round(n / static_cast<double> (nb_threads));
slice = std::max(slice, Index(1));
// [Helper] Inner loop
auto launchRange = [&func] (int k1, int k2) {
for (Index k = k1; k < k2; k++) {
func(k);
}
};
// Create pool and launch jobs
std::vector<std::thread> pool;
pool.reserve(nb_threads);
Index i1 = start;
Index i2 = std::min(start + slice, end);
for (unsigned i = 0; i + 1 < nb_threads && i1 < end; ++i) {
pool.emplace_back(launchRange, i1, i2);
i1 = i2;
i2 = std::min(i2 + slice, end);
}
if (i1 < end) {
pool.emplace_back(launchRange, i1, end);
}
// Wait for jobs to finish
for (std::thread &t : pool) {
if (t.joinable()) {
t.join();
}
}
}
// Serial version for easy comparison
template<typename Index, typename Callable>
static void SequentialFor(Index start, Index end, Callable func) {
for (Index i = start; i < end; i++) {
func(i);
}
}
};
#endif // THREADPOOL_HPP_INCLUDED
It seems that you should simply change:
vec.at(i); // Only returns a reference to the element at index i
into:
vec.at(i)(); // The second () calls the function
--- OR ---
vec[i](); // Same
Hint: What does this do?
vec.at(i);
What do you want it to do?
Unrelatedly, you're using at() when you mean [].
This works:
ThreadPool::ParallelFor(0, (int)vec.size(), [&] (int i)
{
vec[i]();
});
I'm attempting to create an algorithm in C++ which will give me all of the possible combinations of a set of list items (input in a map format). I want to avoid duplicates and make sure to cover all possible combinations. To simplify the example, here's what the input may look like:
map<string, vector<string> > sandwichMap;
sandwichMap["bread"].push_back("wheat");
sandwichMap["bread"].push_back("white");
sandwichMap["meat"].push_back("ham");
sandwichMap["meat"].push_back("turkey");
sandwichMap["meat"].push_back("roastbeef");
sandwichMap["veggie"].push_back("lettuce");
sandwichMap["sauce"].push_back("mustard");
I'd feed this map into the algorithm, and it should spit out a vector with all of the possible combinations (using one of each key type):
wheat+ham+lettuce+mustard
wheat+turkey+lettuce+mustard
wheat+roastbeef+lettuce+mustard
white+ham+lettuce+mustard
white+turkey+lettuce+mustard
white+roastbeef+lettuce+mustard
It needs to work for any map of string vectors. So far I've tried and gotten close, but I end up with duplicate combinations and missed combinations:
sandwichList getCombinations(sandwichMap sMap)
{
locList retList;
int totalCombos = 1;
for (sandwichMapIt i = sMap.begin(); i != sMap.end(); ++i)
{
totalCombos *= i->second.size();
}
retList.resize(totalCombos);
int locCount;
for (sandwichMapIt a = sMap.begin(); a != sMap.end(); ++a)
{
locCount = 0;
for (locListIt l = a->second.begin(); l != a->second.end(); ++l)
{
for (unsigned int i = 0; i < totalCombos / a->second.size(); ++i)
{
retList[i + a->second.size() * locCount] += *l;
}
locCount++;
}
}
return retList;
}
Any help would be greatly appreciated!
Updated code:
#include <vector>
#include <map>
#include <list>
#include <iostream>
typedef std::vector<std::string> strVec;
typedef std::list<std::string> strList;
typedef std::map<std::string, strVec> sandwichMap;
int main()
{
sandwichMap sMap;
sMap["bread"].push_back("wheat");
sMap["bread"].push_back("white");
sMap["meat"].push_back("ham");
sMap["meat"].push_back("turkey");
sMap["meat"].push_back("roastbeef");
sMap["veggie"].push_back("lettuce");
sMap["sauce"].push_back("mustard");
strList finalSandwichList;
for (sandwichMap::iterator i = sMap.begin(); i != sMap.end(); ++i)
{
strList tmpSandwich;
for (strVec::iterator j = i->second.begin(); j != i->second.end(); ++j)
{
if (finalSandwichList.empty())
{
tmpSandwich.push_back(*j);
}
else
{
for (strList::iterator k = finalSandwichList.begin(); k != finalSandwichList.end(); ++k)
tmpSandwich.push_back(*k + "+" + *j);
}
}
tmpSandwich.swap(finalSandwichList);
}
for (strList::iterator i = finalSandwichList.begin(); i != finalSandwichList.end(); ++i)
{
std::cout << *i << std::endl;
}
return 0;
}
//solution
std::list<std::string> result;
for(auto i=sandwichMap.begin(); i!=sandwichMap.end(); ++i) {
std::list<std::string> new_result;
for(auto j=i->second.begin(); j!=i->second.end(); ++j) {
if(result.empty())
new_result.push_back(*j);
else
for(auto k=result.begin(); k!=result.end(); ++k)
new_result.push_back(*k + "+" + *j);
}
new_result.swap(result);
}
This should work :
#include<iostream>
#include<map>
#include<string>
#include<algorithm>
using namespace std;
map<string, vector<string>> sMap;
vector<string> add;
int sett[200], countt;
void solve(map<string, vector<string>>::iterator itt, int ct, vector<string> addd){
vector<string> tmp = itt->second;
if(ct == countt){
for(int j=0;j<addd.size();j++){
cout<<addd[j]<<" ";
}
cout<<endl;
return;
}
itt++;
for(int i=0;i<tmp.size();i++){
//cout<<tmp[i]<<" ";
addd.push_back(tmp[i]);
solve(itt, ct+1, addd);
vector<string>::iterator tempIt = addd.end();
addd.erase(tempIt--);
}
}
int main(){
sMap["bre"].push_back("wh");
sMap["bre"].push_back("whi");
sMap["me"].push_back("ham");
sMap["me"].push_back("tur");
sMap["me"].push_back("rr");
sMap["veg"].push_back("let");
sMap["sau"].push_back("mus");
countt = sMap.size();
solve(sMap.begin(), 0, add);
return 0;
}
I have used backtracking to evaluate every possible combination.
Note : it is in c++11 you might need to change some part of the code for lower version of c++
link to output : http://ideone.com/Ou2411
The code is kinda long because of the helper methods, but it does the job:
#include <vector>
#include <string>
#include <map>
#include <iostream>
using namespace std;
template <class T>
vector<T> Head(const vector<T> &v) {
return vector<T>(v.begin(), v.begin() + 1);
}
template <class T>
vector<T> Tail(const vector<T> &v) {
auto first = v.begin() + 1;
auto last = v.end();
return vector<T>(first, last);
}
template <class T>
vector<T> Concat(const vector<T> &v1, const vector<T> &v2) {
vector<T> result = v1;
result.insert(result.end(), v2.begin(), v2.end());
return result;
}
vector<vector<string>> CombineVectorWithScalar(const vector<vector<string>> &v, const string &scalar) {
vector<vector<string>> result = v;
for (unsigned i = 0; i < v.size(); i++) {
result[i].push_back(scalar);
}
return result;
}
vector<vector<string>> CombineVectorWithVector(const vector<vector<string>> &v1, const vector<string> &v2) {
if (v2.empty()) {
return vector<vector<string>>();
}
else {
auto headCombination = CombineVectorWithScalar(v1, v2.front());
auto tailCombination = CombineVectorWithVector(v1, Tail(v2));
return Concat(headCombination, tailCombination);
}
}
vector<string> GetKeys(const map<string, vector<string>> &mp) {
vector<string> keys;
for (auto it = mp.begin(); it != mp.end(); ++it) {
keys.push_back(it->first);
}
return keys;
}
vector<vector<string>> CombineMapValues(const map<string, vector<string>> &mp) {
vector<string> keys = GetKeys(mp);
vector<vector<string>> result;
auto &firstVector = mp.begin()->second;
for (auto it = firstVector.begin(); it != firstVector.end(); ++it) {
vector<string> oneElementList;
oneElementList.push_back(*it);
result.push_back(oneElementList);
}
vector<string> restOfTheKeys = Tail(keys);
for (auto it = restOfTheKeys.begin(); it != restOfTheKeys.end(); ++it) {
auto ¤tVector = mp.find(*it)->second;
result = CombineVectorWithVector(result, currentVector);
}
return result;
}
void PrintCombinations(const vector<vector<string>> & allCombinations) {
for (auto it = allCombinations.begin(); it != allCombinations.end(); ++it) {
auto currentCombination = *it;
for (auto itInner = currentCombination.begin(); itInner != currentCombination.end(); ++itInner) {
cout << *itInner << " ";
}
cout << endl;
}
}
int main() {
map<string, vector<string> > sandwichMap;
sandwichMap["bread"].push_back("wheat");
sandwichMap["bread"].push_back("white");
sandwichMap["meat"].push_back("ham");
sandwichMap["meat"].push_back("turkey");
sandwichMap["meat"].push_back("roastbeef");
sandwichMap["veggie"].push_back("lettuce");
sandwichMap["sauce"].push_back("mustard");
auto allCombinations = CombineMapValues(sandwichMap);
PrintCombinations(allCombinations);
return 0;
}
void generate_all(std::map<std::string,std::vector<std::string>>::iterator start,
std::vector<std::string::iterator> accomulator,
std::map<std::string,std::vector<std::string>>& sMap){
for (auto it=start; it!=sMap.end(); ++it){
for (auto jt=it->second.begin(); jt!=it->second.end(); jt++){
generate_all(start+1,accomulator.pus_back[jt],sMap);
}
}
if (accomulator.size() == sMap.size()){
// print accomulator
}
}
Call with generate_all(sMap.begin(),aVector,sMap);
If the map is too big to go recursively, you can always generate an equivalent iterative code.
This solution is not recursive. Basically what it does is the following:
Compute how many combinations are actually possible
Know that for each key in the map, you're going to have to add nrCombinations/nrItemsInKey of them in total.
You can see it as a tree growing, branching more and more the more keys you have visited.
If you keep track of how many there are, how spaced they are and where they start you can automatically fill all combinations.
Code
#include <vector>
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, std::vector<std::string> > sandwichMap;
sandwichMap["bread"].push_back("wheat");
sandwichMap["bread"].push_back("white");
sandwichMap["meat"].push_back("ham");
sandwichMap["meat"].push_back("turkey");
sandwichMap["meat"].push_back("roastbeef");
sandwichMap["veggie"].push_back("lettuce");
sandwichMap["sauce"].push_back("mustard");
sandwichMap["sauce"].push_back("mayo");
// Compute just how many combinations there are
int combinationNr = 1;
for ( auto it : sandwichMap ) {
combinationNr *= it.second.size();
}
std::vector<std::vector<std::string>> solutions(combinationNr);
// We start with empty lists, thus we only have one cluster
int clusters = 1, clusterSize = combinationNr;
for ( auto category : sandwichMap ) {
int startIndex = 0;
int itemsNr = category.second.size();
int itemsPerCluster = clusterSize / itemsNr;
for ( auto item : category.second ) {
for ( int c = 0; c < clusters; ++c ) {
for ( int i = 0; i < itemsPerCluster; ++i ) {
// We sequentially fill each cluster with this item.
// Each fill starts offset by the quantity of items
// already added in the cluster.
solutions[startIndex+i+c*clusterSize].push_back(item);
}
}
startIndex += itemsPerCluster;
}
clusters *= itemsNr;
clusterSize = combinationNr / clusters;
}
for ( auto list : solutions ) {
for ( auto element : list ) {
std::cout << element << ", ";
}
std::cout << "\n";
}
return 0;
}
I need to find an element position in an std::vector to use it for referencing an element in another vector:
int find( const vector<type>& where, int searchParameter )
{
for( int i = 0; i < where.size(); i++ ) {
if( conditionMet( where[i], searchParameter ) ) {
return i;
}
}
return -1;
}
// caller:
const int position = find( firstVector, parameter );
if( position != -1 ) {
doAction( secondVector[position] );
}
however vector::size() returns size_t which corresponds to an unsigned integral type that can't directly store -1. How do I signal that the element is not found in a vector when using size_t instead of int as an index?
Take a look at the answers provided for this question: Invalid value for size_t?. Also you can use std::find_if with std::distance to get the index.
std::vector<type>::iterator iter = std::find_if(vec.begin(), vec.end(), comparisonFunc);
size_t index = std::distance(vec.begin(), iter);
if(index == vec.size())
{
//invalid
}
First of all, do you really need to store indices like this? Have you looked into std::map, enabling you to store key => value pairs?
Secondly, if you used iterators instead, you would be able to return std::vector.end() to indicate an invalid result. To convert an iterator to an index you simply use
size_t i = it - myvector.begin();
You could use std::numeric_limits<size_t>::max() for elements that was not found. It is a valid value, but it is impossible to create container with such max index. If std::vector has size equal to std::numeric_limits<size_t>::max(), then maximum allowed index will be (std::numeric_limits<size_t>::max()-1), since elements counted from 0.
std::vector has random-access iterators. You can do pointer arithmetic with them. In particular, this my_vec.begin() + my_vec.size() == my_vec.end() always holds. So you could do
const vector<type>::const_iterator pos = std::find_if( firstVector.begin()
, firstVector.end()
, some_predicate(parameter) );
if( position != firstVector.end() ) {
const vector<type>::size_type idx = pos-firstVector.begin();
doAction( secondVector[idx] );
}
As an alternative, there's always std::numeric_limits<vector<type>::size_type>::max() to be used as an invalid value.
In this case, it is safe to cast away the unsigned portion unless your vector can get REALLY big.
I would pull out the where.size() to a local variable since it won't change during the call. Something like this:
int find( const vector<type>& where, int searchParameter ){
int size = static_cast<int>(where.size());
for( int i = 0; i < size; i++ ) {
if( conditionMet( where[i], searchParameter ) ) {
return i;
}
}
return -1;
}
If a vector has N elements, there are N+1 possible answers for find. std::find and std::find_if return an iterator to the found element OR end() if no element is found. To change the code as little as possible, your find function should return the equivalent position:
size_t find( const vector<type>& where, int searchParameter )
{
for( size_t i = 0; i < where.size(); i++ ) {
if( conditionMet( where[i], searchParameter ) ) {
return i;
}
}
return where.size();
}
// caller:
const int position = find( firstVector, parameter );
if( position != secondVector.size() ) {
doAction( secondVector[position] );
}
I would still use std::find_if, though.
Something like this, I think. find_if_counted.hpp:
#ifndef FIND_IF_COUNTED_HPP
#define FIND_IF_COUNTED_HPP
#include <algorithm>
namespace find_if_counted_impl
{
template <typename Func>
struct func_counter
{
explicit func_counter(Func& func, unsigned &count) :
_func(func),
_count(count)
{
}
template <typename T>
bool operator()(const T& t)
{
++_count;
return _func(t);
}
private:
Func& _func;
unsigned& _count;
};
}
// generic find_if_counted,
// returns the index of the found element, otherwise returns find_if_not_found
const size_t find_if_not_found = static_cast<size_t>(-1);
template <typename InputIterator, typename Func>
size_t find_if_counted(InputIterator start, InputIterator finish, Func func)
{
unsigned count = 0;
find_if_counted_impl::func_counter<Func> f(func, count);
InputIterator result = find_if(start, finish, f);
if (result == finish)
{
return find_if_not_found;
}
else
{
return count - 1;
}
}
#endif
Example:
#include "find_if_counted.hpp"
#include <cstdlib>
#include <iostream>
#include <vector>
typedef std::vector<int> container;
int rand_number(void)
{
return rand() % 20;
}
bool is_even(int i)
{
return i % 2 == 0;
}
int main(void)
{
container vec1(10);
container vec2(10);
std::generate(vec1.begin(), vec1.end(), rand_number);
std::generate(vec2.begin(), vec2.end(), rand_number);
unsigned index = find_if_counted(vec1.begin(), vec1.end(), is_even);
if (index == find_if_not_found)
{
std::cout << "vec1 has no even numbers." << std::endl;
}
else
{
std::cout << "vec1 had an even number at index: " << index <<
" vec2's corresponding number is: " << vec2[index] << std::endl;
}
}
Though I feel like I'm doing something silly... :X Any corrections are welcome, of course.
You probably should not use your own function here.
Use find() from STL.
Example:
list L;
L.push_back(3);
L.push_back(1);
L.push_back(7);
list::iterator result = find(L.begin(), L.end(), 7);
assert(result == L.end() || *result == 7);
Take a vector of integer and a key (that we find in vector )....Now we are traversing the vector until found the key value or last index(otherwise).....If we found key then print the position , otherwise print "-1".
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int>str;
int flag,temp key, ,len,num;
flag=0;
cin>>len;
for(int i=1; i<=len; i++)
{
cin>>key;
v.push_back(key);
}
cin>>num;
for(int i=1; i<=len; i++)
{
if(str[i]==num)
{
flag++;
temp=i-1;
break;
}
}
if(flag!=0) cout<<temp<<endl;
else cout<<"-1"<<endl;
str.clear();
return 0;
}
Get rid of the notion of vector entirely
template< typename IT, typename VT>
int index_of(IT begin, IT end, const VT& val)
{
int index = 0;
for (; begin != end; ++begin)
{
if (*begin == val) return index;
}
return -1;
}
This will allow you more flexibility and let you use constructs like
int squid[] = {5,2,7,4,1,6,3,0};
int sponge[] = {4,2,4,2,4,6,2,6};
int squidlen = sizeof(squid)/sizeof(squid[0]);
int position = index_of(&squid[0], &squid[squidlen], 3);
if (position >= 0) { std::cout << sponge[position] << std::endl; }
You could also search any other container sequentially as well.