I have created a structure that contains a vector of unsigned integers for bitstream handling. Essentially, values are written to this vector in sets that are no more than 64 bits long.
The strange behavior comes into play with different images used. Running the entire code on various images yields strange results. Some images (no correlation to size) will properly encode and write to the ofstream while others will cause a vector emplace_back error at the line "ints.emplace_back(field())".
As I am sure most reading this will suggest, I have added a .reserve line to increase the capacity. This does fix this problem, but then (for the same images) a new problem occurs when writing the vector to the file. Now an error occurs in fstream at line
_Count -= _CSTD fwrite(_Ptr, sizeof(_Elem), static_cast<size_t>(_Count), _Myfile);
But again, this error does not happen for most of the other images that are both the same dimensions or larger or smaller. Any reason for this strange behavior? Or perhaps suggestions on a way to fix the fwrite error? I tried shrink_to_fit() but that causes the same malloc error when shrinking to fit.
Here is the relevant code:
(structures)
struct field {
private:
uint32_t bits;
public:
field() : bits(0) {}
operator uint32_t() { return bits; }
inline uint32_t pack() { return bits; }
field& set_bits(uint32_t val, uint8_t pos) {
bits |= (val << pos);
return *this;
}
uint32_t get_bits(uint8_t a, uint8_t b) {
return (bits >> a) & ~(0xFFFFFFFF << (b - a));
}
};
struct bstream {
private:
std::vector<field> ints;
size_t position;
size_t length;
public:
bstream() : position(0), ints(0), length(0) {}
bstream(const bstream& p1) { position = p1.position; ints = p1.ints; length = p1.length; }
field* data() { return ints.data(); }
int get_size() { return (ceil(position / 32.0)); } // returns how many bytes there are
int max_size() { return ints.max_size(); }
int size() { return ints.size(); }
int capacity() { return ints.capacity(); }
bstream& resize(int size) { ints.resize(floor(size / 4)); length = floor(size / 4); return *this; }
bstream& reserve(int size) { ints.reserve(size); return *this; }
bstream& shrink_to_fit() { ints.shrink_to_fit(); return *this; }
bstream& push_chunk(uint32_t C, int Q) {
const int a = (position % 32);
const int b = a + Q;
if (a == 0)
ints.emplace_back(field());
if (b > 32) {
ints.back().set_bits(C, a);
position += (32 - a);
this->push_chunk(C >> (32 - a), b - 32);
}
else {
ints.back().set_bits(C, a);
position += Q;
}
return *this;
}
uint32_t pop_chunk(int Q) {}
bstream& write_int(int C, int Q, const int qmin, bool is_signed) {
this->push_chunk(abs(C) >> qmin, Q - qmin);
if (is_signed && (abs(C) >> qmin) != 0)
this->push_chunk(int(0) < C, 1);
return *this;
}
int read_int(int Q, const int qmin, bool is_signed) {}
bstream& write_descent(int A, int B, const int qmin) {}
int read_descent(int A, const int qmin) {}
bstream& encode_group(int* Q, int* C, int index, int qmin, int sizeQ, int sizeC) {}
bstream& encode_coeffs(int Qg, int Q, int* C, int index, int qmin) {}
void decode_group(int* Q, int* C, int index, int qmin, int sizeQ, int sizeC) {}
void decode_coeffs(int Qg, int& Q, int* C, int index, int qmin) {}
void print() {}
};
(Line used to write to ofstream)
outFile->write(reinterpret_cast<char*>(STREAM.data()), 4.0 * STREAM.get_size());
Related
class
{
public:
void func(const int val, const bool flag)
{
if(flag)
{
while(!lower.empty() && val <= lower.top())
{
// do a bunch of stuff with lower
}
}
else
{
while(!higher.empty() && val >= higher.top())
{
// do a bunch of stuff with higher, but it's the same stuff as would've done
// for lower
}
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
I'm trying to figure out a better way to write the clauses because currently, I have a lot of duplicate code in both. The only difference is one clause operates on lower and the other on higher and the <= in the first clause is changed to >= higher in the second one.
I could wrap the clause in a helper function and call it in each clause (and pass in the lower and higher as an argument), e.g.,
class
{
public:
void func(const int val, const bool flag)
{
if(flag)
{
helper(lower, comparer);
}
else
{
helper(lower, comparer);
}
}
void helper(std::stack<int> &st)
{
// do a bunch of stuff with st
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
I'm not sure if this is a good idea and if it is, I'm not sure how to get around the >= vs. <=. I'm hoping for suggestions on my design!
You can do something like the following:
class
{
public:
void func(const int val, const bool flag)
{
std::stack<int> *st;
bool (*compare)(int, int);
if (flag)
{
st = &lower;
compare = [](int a, int b){ return a <= b; };
}
else
{
st = &higher;
compare = [](int a, int b){ return a >= b; };
}
while (!st->empty() && compare(val, st->top()))
{
// do a bunch of stuff with *st
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
Alternatively, using a helper would certainly work, too:
class
{
public:
void func(const int val, const bool flag)
{
if (flag)
func_helper(lower, val, std::less_equal{});
else
func_helper(higher, val, std::greater_equal{});
}
private:
std::stack<int> lower;
std::stack<int> higher;
template<typename Comparer>
void func_helper(stack<int> &st, const int val, Comparer compare)
{
while (!st.empty() && compare(val, st.top()))
{
// do a bunch of stuff with st
}
}
}
How about something like this
class
{
public:
void func(const int val, const bool flag)
{
int sign = 1;
std::stack<int>* higher_or_lower = &higher;
if(flag)
{
higher_or_lower = &lower;
sign = -1;
}
while(!higher_or_lower->empty() && sign*val >= sign*higher_or_lower->top())
{
// do a bunch of stuff with higher_or_lower
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
The higher_or_lower covers both stacks and the sign takes care of less than vs. greater than.
Or a bit more compact:
class C
{
public:
void func(const int val, const bool flag)
{
const std::stack<int>* st[] = {&lower, &higher};
bool (*compare[])(int, int) = { [](int a, int b) { return a <= b; } , [](int a, int b) { return a >= b; } };
while (!st[flag]->empty() && compare[flag](val, st[flag]->top()))
{
// do a bunch of stuff with *st
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
};
Okay so am trying to make a data structure that maintains a heap of data in order to solve within the compile-time limit. https://open.kattis.com/problems/annoyedcoworkers
I might be in over my head since I just started coding in the last year or so and I just learned about sorting and vectors last week and heap data structures yesterday. But I am really interested in solving this problem.
Anyway here goes I first started to solve this problem with selection sort... needless to say it took way too long.
Then I started looking into making a heap data structure that yields values sorted order,
which brought me to priority_queue
After about 9 hours of trying different methods, this is the closest I've gotten to solving the problem.
does anyone have any suggestions as to why after 25/27 test cases my code returns a wrong answer?
Here is my code :
// C++ program to use priority_queue to implement Min Heap
// for user defined class
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
// User defined class, coworker
class CoworkerT
{
private:
int a;
int d;
public:
CoworkerT(int _a, int _d)
{
a = _a;
d = _d;
}
int SimAddAD() const
{
int aD;
aD = a + d;
return aD;
}
int AddAD()
{
a = a + d;
return a;
}
int getA() const {
return a;
}
int getD() const {
return d;
}
};
// To compare two coworkers possible a value
class Min
{
public:
int operator() (const CoworkerT& p1, const CoworkerT& p2)
{
return p1.SimAddAD() > p2.SimAddAD();
}
};
//compare two a values between coworkers
class Max
{
public:
int operator() (const CoworkerT& p1, const CoworkerT& p2)
{
return p1.getA() < p2.getA();
}
};
int AskForA() {
int a;
cin >> a;
return a;
}
int AskForD() {
int d;
cin >> d;
return d;
}
priority_queue <CoworkerT, vector<CoworkerT>, Max >
PopulateMax(priority_queue <CoworkerT, vector<CoworkerT>, Max > max,
priority_queue <CoworkerT, vector<CoworkerT>, Min > min) {
while (min.empty() == false)
{
CoworkerT e = min.top();
max.push(CoworkerT(e.getA(), e.getD()));
min.pop();
}
return max;
}
// Driver code
int main()
{
int h, c, i, a, d;
cin >> h >> c;
// Creates a Min heap of points (order by possible a +d combination )
priority_queue <CoworkerT, vector<CoworkerT>, Min > pq;
// Creates a Max heap of points (order by actual a value )
priority_queue <CoworkerT, vector<CoworkerT>, Max > max;
// Insert points into the min heap
for (int i = 0; i < c; i++) {
a = AskForA();
d = AskForD();
pq.push(CoworkerT(a, d));
}
i = 0;
while (i < h) {
CoworkerT e = pq.top();
a = e.AddAD();
d = e.getD();
pq.pop();
pq.push(CoworkerT(a, d));
i++;
}
max = PopulateMax(max, pq);
CoworkerT eMax = max.top();
cout << eMax.getA() << endl;
return 0;
}
I just want to say that I ended up using something similar to my original algorithm using the heap. The problem was my use of int I switched to an unsigned long long int ~(though that might have been overkill?) and it worked like a charm.
// C++ program to use priority_queue to implement Min Heap
// for user defined class
#include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// User defined class, coworker
class CoworkerT {
private:
unsigned long long int a;
unsigned long long int d;
public:
CoworkerT(unsigned long long int _a, unsigned long long int _d){
a = _a;
d = _d;
}
unsigned long long int SimAddAD() const{
return a + d;
}
unsigned long long int AddAD(){
return a + d;;
}
unsigned long long int getA() const {
return a;
}
unsigned long long int getD() const {
return d;
}
};
//compare two coworkers possible a + d values
struct MinSort {
bool operator()(const CoworkerT& p1, const CoworkerT& p2) const {
return p1.SimAddAD() < p2.SimAddAD();
}
};
//compare two coworkers possible a + d values ~for some reason heap lesser than or greater need to be reverse of operator for sort???
struct Min {
bool operator()(const CoworkerT& p1, const CoworkerT& p2) const {
return p1.SimAddAD() > p2.SimAddAD();
}
};
//compare two a values between coworkers
struct MaxSort {
bool operator()(const CoworkerT& p1, const CoworkerT& p2) const {
return p1.getA() > p2.getA();
}
};
void FindAndPrintMax(vector<CoworkerT>& max) {
sort(max.begin(), max.end(), MaxSort());
CoworkerT minMax = max.front();
cout << minMax.getA();
}
void InputCoworkersAD(vector<CoworkerT>& min, unsigned long long int& h, unsigned long long int& c) {
int a, d, i;
cin >> h >> c;
// Insert a and d into the vector
if (h <= 100000 && h >= 1 && c <= 100000 && c >= 1) {
for (i = 0; i < c; i++) {
cin >> a >> d;
min.push_back(CoworkerT(a, d));
}
}
make_heap(min.begin(), min.end(), Min());
}
void AskForHelp(vector<CoworkerT>& min, unsigned long long int h) {
int i = 0;
while (i < h) {
push_heap(min.begin(), min.end(), Min());
CoworkerT e = min.front();
pop_heap(min.begin(), min.end(), Min());
min.pop_back();
min.push_back(CoworkerT(e.AddAD(), e.getD()));
i++;
}
}
// Driver code
int main()
{
unsigned long long int h, c;
vector<CoworkerT> min;
InputCoworkersAD(min, h, c);
AskForHelp(min, h);
FindAndPrintMax(min);
return 0;
}
I'm attempting to get a basic constant forward-iterator to work in C++.
namespace Rcpp {
class SparseMatrix {
public:
IntegerVector i, p;
NumericVector x;
int begin_col(int j) { return p[j]; };
int end_col(int j) { return p[j + 1]; };
class iterator {
public:
int index;
iterator(SparseMatrix& g) : parent(g) {}
iterator(int ind) { index = ind; }; // ERROR!
bool operator!=(int x) const { return index != x; };
iterator operator++(int) { ++index; return (*this); };
int row() { return parent.i[index]; };
double value() { return parent.x[index]; };
private:
SparseMatrix& parent;
};
};
}
My intention is to use the iterator in contexts similar to the following:
// sum of values in column 7
Rcpp::SparseMatrix A(nrow, ncol, fill::random);
double sum = 0;
for(Rcpp::SparseMatrix::iterator it = A.begin_col(7); it != A.end_col(7); it++)
sum += it.value();
Two questions:
The compiler throws an error on the line indicated above: uninitialized reference member in 'class Rcpp::SparseMatrix&' [-fpermissive]. How can this be fixed?
How might double value() { return parent.x[index]; }; be re-worked to return a pointer to the value rather than a copy of the value?
A little context on the SparseMatrix class: like a dgCMatrix in R, this object of class SparseMatrix consists of three vectors:
i holds row pointers for every element in x
p gives indices in i which correspond to the start of each column
x contains non-zero values
Thanks to #Evg, here's the solution:
namespace Rcpp {
class SparseMatrix {
public:
IntegerVector i, p;
NumericVector x;
class iterator {
public:
int index;
iterator(SparseMatrix& g, int ind) : parent(g) { index = ind; }
bool operator!=(iterator x) const { return index != x.index; };
iterator& operator++() { ++index; return (*this); };
int row() { return parent.i[index]; };
double& value() { return parent.x[index]; };
private:
SparseMatrix& parent;
};
iterator begin_col(int j) { return iterator(*this, p[j]); };
iterator end_col(int j) { return iterator(*this, p[j + 1]); };
};
}
And it can be used as follows, for instance, to calculate colSums:
//[[Rcpp::export]]
Rcpp::NumericVector Rcpp_colSums(Rcpp::SparseMatrix& A) {
Rcpp::NumericVector sums(A.cols());
for (int i = 0; i < A.cols(); ++i)
for (Rcpp::SparseMatrix::iterator it = A.begin_col(i); it != A.end_col(i); it++)
sums(i) += it.value();
return sums;
}
And, the above function is faster than RcppArmadillo, RcppEigen, and R::Matrix equivalents when microbenchmarked from R!
Edit:
The above syntax is inspired by Armadillo. I've come to realize that a slightly different syntax (which involves fewer constructions) gives an iterator similar to Eigen:
class col_iterator {
public:
col_iterator(SparseMatrix& ptr, int col) : ptr(ptr) { indx = ptr.p[col]; max_index = ptr.p[col + 1]; }
operator bool() const { return (indx != max_index); }
col_iterator& operator++() { ++indx; return *this; }
const double& value() const { return ptr.x[indx]; }
int row() const { return ptr.i[indx]; }
private:
SparseMatrix& ptr;
int indx, max_index;
};
Which can then be used like this:
int col = 0;
for (Rcpp::SparseMatrix::col_iterator it(A, col); it; ++it)
Rprintf("row: %3d, value: %10.2e", it.row(), it.value());
I need an efficient implementation of a vector with multiple rows, each having the same number of columns, which is not too ugly in C++. Currently I have the following:
class BaseVector {
protected: // variables
int64_t _capacity;
int64_t _nColumns;
protected:
template<typename taItem> void Allocate(taItem * &p, const int64_t nItems) {
p = static_cast<taItem*>(MemPool::Instance().Acquire(sizeof(taItem)*nItems));
if (p == nullptr) {
__debugbreak();
}
}
template<typename taItem> void Reallocate(taItem * &p, const int64_t newCap) {
taItem *np;
Allocate(np, newCap);
Utils::AlignedNocachingCopy(np, p, _nColumns * sizeof(taItem));
MemPool::Instance().Release(p, _capacity * sizeof(taItem));
p = np;
}
// Etc for Release() operation
public:
explicit BaseVector(const int64_t initCap) : _capacity(initCap), _nColumns(0) { }
void Clear() { _nColumns = 0; }
int64_t Size() const { return _nColumns; }
};
class DerivedVector : public BaseVector {
__m256d *_pRowA;
__m256i *_pRowB;
uint64_t *_pRowC;
uint8_t *_pRowD;
// Etc. for other rows
public:
DerivedVector(const int64_t nColumns) : BaseVector(nColumns) {
Allocate(_pRowA, nColumns);
Allocate(_pRowB, nColumns);
Allocate(_pRowC, nColumns);
Allocate(_pRowD, nColumns);
// Etc. for the other rows
}
void IncSize() {
if(_nColumns >= _capacity) {
const int64_t newCap = _capacity + (_capacity >> 1) + 1;
Reallocate(_pRowA, newCap);
Reallocate(_pRowB, newCap);
Reallocate(_pRowC, newCap);
Reallocate(_pRowD, newCap);
// Etc. for other rows
_capacity = newCap;
}
_nColumns++;
}
~DerivedVector() {
// Call here the Release() operation for all rows
}
};
The problem with this approach is that there can be 30 rows, so I have to type manually (and repeat myself) 30 times Allocate, 30 times Reallocate, 30 times Release, etc.
So is there a way in C++ to keep this code DRY and fast? I am ok with macros, but not heavy polymorphism in each access to a cell in the vector because this would kill performance.
I post here to ask if there is a way to alternate different strategies of branching. Let me explain, I have an efficient branching strategy which we'll call the strategy A. The biggest problem is that the strategy A cannot be used that often. So when I cannot use the strategy A, I use another strategy, which I'll call the strategy B, which is less efficient.
The documentation says that:
Brancher order. Creating a brancher registers it with its home space. A space maintains a queue of its branchers in that the brancher that is registered first is also used first for
branching. The first brancher in the queue of branchers is referred to as the current brancher.
So, I supposed that if I post the brancher A then the brancher B, the brancher A will has priority and each time the status of A says there is no branching to do, the brancher B will be used. Seems like I was wrong because when the status of a brancher return false, it is never called again.
Here is a "minimal example":
#include <gecode/minimodel.hh>
#include <iostream>
using namespace Gecode;
using namespace std;
class MyChoice : public Choice {
public:
int pos; // Position of the variable
int val; // Value of to assign
MyChoice(const Brancher& b, int pos0, int val0)
: Choice(b,2), pos(pos0), val(val0) {}
// Report size occupied
virtual size_t size(void) const {
return sizeof(*this);
}
// Archive into e
virtual void archive(Archive& e) const {
Choice::archive(e);
e << pos << val;
}
};
class BranchA : public Brancher {
protected:
ViewArray<Int::IntView> x;
public:
BranchA(Home home, ViewArray<Int::IntView>& x0)
: Brancher(home), x(x0) {}
static void post(Home home, ViewArray<Int::IntView>& x) {
(void) new (home) BranchA(home,x);
}
virtual size_t dispose(Space& home) {
(void) Brancher::dispose(home);
return sizeof(*this);
}
BranchA(Space& home, bool share, BranchA& b)
: Brancher(home,share,b) {
x.update(home,share,b.x);
}
virtual Brancher* copy(Space& home, bool share) {
return new (home) BranchA(home,share,*this);
}
// status
virtual bool status(const Space& home) const {
for (int i=0; i<x.size(); i++)
if (!x[i].assigned())
return !i%2 && x[i].in(1);
return false;
}
// choice
virtual Choice* choice(Space& home) {
for (int i=0; true; i++)
if (!x[i].assigned())
return new MyChoice(*this,i,1);
GECODE_NEVER;
return NULL;
}
virtual Choice* choice(const Space&, Archive& e) {
int pos, val;
e >> pos >> val;
return new MyChoice(*this, pos, val);
}
// commit
virtual ExecStatus commit(Space& home,
const Choice& c,
unsigned int a) {
const MyChoice& pv = static_cast<const MyChoice&>(c);
int pos=pv.pos, val=pv.val;
if (a == 0)
return me_failed(x[pos].eq(home,val)) ? ES_FAILED : ES_OK;
else
return me_failed(x[pos].nq(home,val)) ? ES_FAILED : ES_OK;
}
};
void branchA(Home home, const IntVarArgs& x) {
if (home.failed()) return;
ViewArray<Int::IntView> y(home,x);
BranchA::post(home,y);
}
// BranchB //////////////////////////////////////////////////////
class BranchB : public Brancher {
protected:
ViewArray<Int::IntView> x;
public:
BranchB(Home home, ViewArray<Int::IntView>& x0)
: Brancher(home), x(x0) {}
static void post(Home home, ViewArray<Int::IntView>& x) {
(void) new (home) BranchB(home,x);
}
virtual size_t dispose(Space& home) {
(void) Brancher::dispose(home);
return sizeof(*this);
}
BranchB(Space& home, bool share, BranchB& b)
: Brancher(home,share,b) {
x.update(home,share,b.x);
}
virtual Brancher* copy(Space& home, bool share) {
return new (home) BranchB(home,share,*this);
}
// status
virtual bool status(const Space& home) const {
for (int i=0; i<x.size(); i++)
if (!x[i].assigned())
return i%2 && x[i].in(2);
return false;
}
// choice
virtual Choice* choice(Space& home) {
for (int i=0; true; i++)
if (!x[i].assigned())
return new MyChoice(*this,i,2);
GECODE_NEVER;
return NULL;
}
virtual Choice* choice(const Space&, Archive& e) {
int pos, val;
e >> pos >> val;
return new MyChoice(*this, pos, val);
}
// commit
virtual ExecStatus commit(Space& home,
const Choice& c,
unsigned int a) {
const MyChoice& pv = static_cast<const MyChoice&>(c);
int pos=pv.pos, val=pv.val;
if (a == 0)
return me_failed(x[pos].eq(home,val)) ? ES_FAILED : ES_OK;
else
return me_failed(x[pos].nq(home,val)) ? ES_FAILED : ES_OK;
}
};
void branchB(Home home, const IntVarArgs& x) {
if (home.failed()) return;
ViewArray<Int::IntView> y(home,x);
BranchB::post(home,y);
}
// Minimal Space ///////////////////////////////////////
class TestSpace : public Space {
protected:
IntVarArray x;
public:
TestSpace(int size)
: x(*this, size, 0, 10) {
branchA(*this, x);
branchB(*this, x);
}
TestSpace (bool share, TestSpace& s)
: Space(share, s) {
x.update(*this, share, s.x);
}
virtual Space* copy (bool share) {
return new TestSpace(share, *this);
}
void print(std::ostream& os) {
os << "x= " << x << endl;
}
};
// Minimal Main //////////////////////:
int main (int, char**) {
// create model and search engine
TestSpace* m = new TestSpace(10);
DFS<TestSpace> e(m);
delete m;
// search and print all solutions
while (TestSpace* s = e.next()) {
s->print(cout); delete s;
}
return 0;
}
In this example, the status of the brancher A return true if the next variable to assign is on an even index and if the variable can take the value of 1 (false else). And the brancher B status return true if the next variable to assign is on an odd index and if the variable can take the value of 2 (false else).
With that code I expected to get the solutions [1, 2, 1, 2, ...] and [!1, !2, !1, !2, ...] (and others combinations like [!1, 2, 1, !2, ...]) but since the branchers are disposed when their status return false, only the two first variables have been assigned.
Is there a good way to make the brancher not being disposed after its status return false (or to alternate two differents branching strategies) or should I merge the two branchers into one ?
If it may help someone, here is the solution I used.
As advised by Patrick Trentin, I unified the control by making a third brancher which is a vector of branchers. Here is the implementation I used:
The header branchAllInOne.h:
#include <gecode/minimodel.hh>
using namespace Gecode;
using namespace std;
class BranchAllInOne : public Brancher {
protected:
// Queue of brancher (may be better with ActorLink)
vector<Actor *> queue;
// Every brancher are in the brancher
BrancherGroup group;
mutable int toChoose;
class ChoiceAndID : public Choice {
public:
// Choice of the brancher used
Choice* c;
/// ID of brancher used
unsigned int id;
ChoiceAndID(const Brancher& b, Choice * c, unsigned int id);
virtual ~ChoiceAndID();
virtual size_t size(void) const ;
virtual void archive(Archive& e) const ;
};
public:
BranchAllInOne(Home home);
virtual size_t dispose(Space& home);
BranchAllInOne(Home home, bool share, BranchAllInOne& b);
virtual ~BranchAllInOne();
/**
* Check status of brancher, set toChoose value to the ID of the first
* brancher with alternative left
**/
virtual bool status(const Space&) const ;
/**
* Let the brancher of ID toChoose make the choice
*/
virtual Choice* choice(Space&);
virtual Choice* choice(const Space&, Archive& e);
/**
* Let the brancher of ID toChoose commit his choice
*/
virtual ExecStatus commit(Space& home, const Choice& _c, unsigned int a);
/// Copy brancher
virtual Actor* copy(Space& home, bool share);
/// Post brancher
static BranchAllInOne * post(Home home);
virtual void print(const Space& home,
const Choice& c,
unsigned int a,
ostream& o) const ;
void pushBrancher(Space& home, Brancher *b);
};
BranchAllInOne * branchAllInOne(Home home);
The implementation branchAllInOne.cpp:
#include "branchAllInOne.h"
static Brancher * ActorToBrancher(Actor *a);
// Choice implementation
BranchAllInOne::ChoiceAndID::ChoiceAndID(const Brancher& b, Choice * c0, unsigned int id0)
: Choice(b, c0->alternatives()),
c(c0),
id(id0){}
BranchAllInOne::ChoiceAndID::~ChoiceAndID() {
delete c;
}
size_t BranchAllInOne::ChoiceAndID::size(void) const {
return sizeof(*this) + c->size();
}
void BranchAllInOne::ChoiceAndID::archive(Archive& e) const {
Choice::archive(e);
c->archive(e);
}
BranchAllInOne::BranchAllInOne(Home home)
: Brancher(home),
toChoose(-1) {
home.notice(*this,AP_DISPOSE);
}
// brancher
BranchAllInOne * BranchAllInOne::post(Home home) {
return new (home) BranchAllInOne(home);
}
size_t BranchAllInOne::dispose(Space& home) {
home.ignore(*this, AP_DISPOSE);
size_t size = queue.size() * sizeof(Actor*);
for (unsigned int i = queue.size() ; i--;) {
size += ActorToBrancher(queue[i])->dispose(home);
}
queue.~vector();
// Making sure to kill each brancher inserted in the queue (may be useless)
group.kill(home);
(void) Brancher::dispose(home);
return sizeof(*this) + size;
}
BranchAllInOne::BranchAllInOne(Home home, bool share, BranchAllInOne& b)
: Brancher(home, share, b),
queue(b.queue.size()),
toChoose(b.toChoose){
for (unsigned int i = 0 ; i < queue.size() ; i++)
queue[i] = b.queue[i]->copy(home, share);
}
BranchAllInOne::~BranchAllInOne() {
for (unsigned int i = 0 ; i < queue.size() ; i++) {
delete queue[i];
}
queue.~vector();
}
Actor* BranchAllInOne::copy(Space& home, bool share){
return new (home) BranchAllInOne(home, share, *this);
}
// status
bool BranchAllInOne::status(const Space& s) const {
for (unsigned int i = 0 ; i < queue.size() ; i++) {
if (ActorToBrancher(queue[i])->status(s)) {
toChoose = i;
return true;
}
}
std::cout << std::endl;
return false;
}
// choice
Choice* BranchAllInOne::choice(Space& s) {
ChoiceAndID* res = new ChoiceAndID(*this,
const_cast<Choice *>(ActorToBrancher(queue[toChoose])->choice(s)),
toChoose);
toChoose = -1;
return res;
}
Choice* BranchAllInOne::choice(const Space& s, Archive& e) {
return new ChoiceAndID(*this,
const_cast<Choice *>(ActorToBrancher(queue[toChoose])->choice(s, e)),
toChoose);
}
// Perform commit for choice \a _c and alternative \a a
ExecStatus BranchAllInOne::commit(Space& home, const Choice& c, unsigned int a) {
const BranchAllInOne::ChoiceAndID& ch = static_cast<const BranchAllInOne::ChoiceAndID&>(c);
return ActorToBrancher(queue[ch.id])->commit(home, const_cast<Choice&>(*ch.c), a);
}
void BranchAllInOne::print(const Space& home,
const Choice& c,
unsigned int a,
ostream& o) const {
const BranchAllInOne::ChoiceAndID& ch = static_cast<const BranchAllInOne::ChoiceAndID&>(c);
o << ch.id << ": ";
ActorToBrancher(queue[ch.id])->print(home, *(ch.c), a, o);
}
void BranchAllInOne::pushBrancher(Space &home, Brancher *b) {
queue.push_back(b);
group.move(home, *b);
}
static Brancher * ActorToBrancher(Actor *a) {
return dynamic_cast<Brancher *>(a);
}
// end of BranchAllInOne implementation
BranchAllInOne* branchAllInOne(Home home) {
if (home.failed()) return NULL;
return BranchAllInOne::post(home);
}
I've made some modifications to get a pointer to branchers I want to put in the vector (that include the post function of each branchers):
brancherA example:
BranchA * BranchA::post(Home home, ViewArray<Int::IntView>& x) {
return new (home) BranchA(home,x);
}
BranchA * branchA(Home home, const IntVarArgs& x) {
if (home.failed()) return NULL;
ViewArray<Int::IntView> y(home,x);
return BranchA::post(home,y);
}
The space has also been modified:
TestSpace::TestSpace(int size)
: x(*this, size, 0, 10) {
BranchAllInOne * b = branchAllInOne(*this);
b->pushBrancher(*this, branchA(*this, x));
b->pushBrancher(*this, branchB(*this, x));
}
I tested it with and without Gist and only got a memory leak of a pointer for each brancher put in the vector (here only two). A small problem remain is that branchers put in the vector are also scheduled after the third brancher stoped (but their status return false).