Refactor edoBinomialMulti to allow more complex data structures
Refactor distribution, sampler and estimator related to the multi-binomial distribution. This introduce tomic methods which may be overloaded for data structures more complex than eoReal of vector of bool (the default implentation).
This commit is contained in:
parent
bc746575ad
commit
5caa49012f
3 changed files with 89 additions and 42 deletions
|
|
@ -49,6 +49,13 @@ public:
|
||||||
edoBinomialMulti( T initial_probas )
|
edoBinomialMulti( T initial_probas )
|
||||||
: T(initial_probas) {}
|
: T(initial_probas) {}
|
||||||
|
|
||||||
|
/** Initialize all the probabilities to a constant
|
||||||
|
*
|
||||||
|
* 0.5 by default
|
||||||
|
*/
|
||||||
|
edoBinomialMulti( unsigned int rows, unsigned int cols, double proba=0.5 )
|
||||||
|
: T::Constant(rows,cols,proba) {}
|
||||||
|
|
||||||
/** Constructor without any assumption.
|
/** Constructor without any assumption.
|
||||||
*/
|
*/
|
||||||
edoBinomialMulti() {}
|
edoBinomialMulti() {}
|
||||||
|
|
|
||||||
|
|
@ -41,55 +41,72 @@ Authors:
|
||||||
template< class EOT, class D = edoBinomialMulti<EOT> >
|
template< class EOT, class D = edoBinomialMulti<EOT> >
|
||||||
class edoEstimatorBinomialMulti : public edoEstimator<D>
|
class edoEstimatorBinomialMulti : public edoEstimator<D>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
D eot2d( EOT from, unsigned int rows, unsigned int cols ) // FIXME maybe more elegant with Eigen::Map?
|
/** Decide whether a given element of the distribution is true or false.
|
||||||
{
|
*
|
||||||
assert( rows > 0 );
|
* The default implementation is to set the item to the value of the atom itself
|
||||||
assert( from.size() == rows );
|
* (which is a boolean in the basic version).
|
||||||
assert( cols > 0 );
|
* If you have a more complex data structure, you can just overload this.
|
||||||
|
*/
|
||||||
|
virtual void make( D & to, unsigned int i, unsigned int j, typename EOT::AtomType::const_iterator iatom )
|
||||||
|
{
|
||||||
|
to(i,j) = *iatom;
|
||||||
|
}
|
||||||
|
|
||||||
D to( Eigen::MatrixXd(rows, cols) );
|
/** Transliterate a EOT in a boolean matrix
|
||||||
for( unsigned int i=0; i < rows; ++i ) {
|
*/
|
||||||
assert( from[i].size() == cols );
|
D eot2d( const EOT & from, unsigned int rows, unsigned int cols ) // FIXME maybe more elegant with Eigen::Map?
|
||||||
for( unsigned int j=0; j < cols; ++j ) {
|
{
|
||||||
to(i,j) = from[i][j];
|
assert( rows > 0 );
|
||||||
}
|
assert( from.size() == rows );
|
||||||
|
assert( cols > 0 );
|
||||||
|
|
||||||
|
D to( Eigen::MatrixXd(rows, cols) );
|
||||||
|
unsigned int i=0;
|
||||||
|
for( typename EOT::const_iterator irow = from.begin(), end=from.end(); irow != end; ++irow ) {
|
||||||
|
assert( irow->size() == cols );
|
||||||
|
unsigned int j=0;
|
||||||
|
for( typename EOT::AtomType::const_iterator icol = irow->begin(), end=irow->end(); icol != end; ++icol ) {
|
||||||
|
make( to, i, j, icol );
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
return to;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
return to;
|
||||||
/** The expected EOT interface is the same as an Eigen3::MatrixXd.
|
}
|
||||||
*/
|
|
||||||
D operator()( eoPop<EOT>& pop )
|
|
||||||
{
|
|
||||||
unsigned int popsize = pop.size();
|
|
||||||
assert(popsize > 0);
|
|
||||||
|
|
||||||
unsigned int rows = pop[0].size();
|
public:
|
||||||
assert( rows > 0 );
|
/** The expected EOT interface is the same as an Eigen3::MatrixXd.
|
||||||
unsigned int cols = pop[0][0].size();
|
*/
|
||||||
assert( cols > 0 );
|
D operator()( eoPop<EOT>& pop )
|
||||||
|
{
|
||||||
|
unsigned int popsize = pop.size();
|
||||||
|
assert(popsize > 0);
|
||||||
|
|
||||||
D probas( D::Zero(rows, cols) );
|
unsigned int rows = pop.begin()->size();
|
||||||
|
assert( rows > 0 );
|
||||||
|
unsigned int cols = pop.begin()->begin()->size();
|
||||||
|
assert( cols > 0 );
|
||||||
|
|
||||||
// We still need a loop over pop, because it is an eoVector
|
D probas( D::Zero(rows, cols) );
|
||||||
for (unsigned int i = 0; i < popsize; ++i) {
|
|
||||||
D indiv = eot2d( pop[i], rows, cols );
|
|
||||||
assert( indiv.rows() == rows && indiv.cols() == cols );
|
|
||||||
|
|
||||||
// the EOT matrix should be filled with 1 or 0 only
|
// We still need a loop over pop, because it is an eoVector
|
||||||
assert( indiv.sum() <= popsize );
|
for (unsigned int i = 0; i < popsize; ++i) {
|
||||||
|
D indiv = eot2d( pop[i], rows, cols );
|
||||||
|
assert( indiv.rows() == rows && indiv.cols() == cols );
|
||||||
|
|
||||||
probas += indiv / popsize;
|
// the EOT matrix should be filled with 1 or 0 only
|
||||||
|
assert( indiv.sum() <= popsize );
|
||||||
|
|
||||||
// sum and scalar product, no size pb expected
|
probas += indiv / popsize;
|
||||||
assert( probas.rows() == rows && probas.cols() == cols );
|
|
||||||
}
|
|
||||||
|
|
||||||
return probas;
|
// sum and scalar product, no size pb expected
|
||||||
|
assert( probas.rows() == rows && probas.cols() == cols );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return probas;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WITH_EIGEN
|
#endif // WITH_EIGEN
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,24 @@ template< class EOT, class D = edoBinomialMulti<EOT> >
|
||||||
class edoSamplerBinomialMulti : public edoSampler<D>
|
class edoSamplerBinomialMulti : public edoSampler<D>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef typename EOT::AtomType AtomType;
|
||||||
|
|
||||||
|
/** Called if the sampler draw the item at (i,j)
|
||||||
|
*
|
||||||
|
* The default implementation is to push back a true boolean.
|
||||||
|
* If you have a more complex data structure, you can just overload this.
|
||||||
|
*/
|
||||||
|
virtual void make_true( AtomType & atom, unsigned int i, unsigned int j )
|
||||||
|
{
|
||||||
|
atom.push_back( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @see make_true */
|
||||||
|
virtual void make_false( AtomType & atom, unsigned int i, unsigned int j )
|
||||||
|
{
|
||||||
|
atom.push_back( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
EOT sample( D& distrib )
|
EOT sample( D& distrib )
|
||||||
{
|
{
|
||||||
unsigned int rows = distrib.rows();
|
unsigned int rows = distrib.rows();
|
||||||
|
|
@ -52,17 +70,22 @@ public:
|
||||||
assert(cols > 0);
|
assert(cols > 0);
|
||||||
|
|
||||||
// The point we want to draw
|
// The point we want to draw
|
||||||
// x = {x1, x2, ..., xn}
|
// X = {x1, x2, ..., xn}
|
||||||
|
// with xn a container of booleans
|
||||||
EOT solution;
|
EOT solution;
|
||||||
|
|
||||||
// Sampling all dimensions
|
// Sampling all dimensions
|
||||||
for( unsigned int i = 0; i < rows; ++i ) {
|
for( unsigned int i = 0; i < rows; ++i ) {
|
||||||
typename EOT::AtomType vec;
|
AtomType atom;
|
||||||
for( unsigned int j = 0; j < cols; ++j ) {
|
for( unsigned int j = 0; j < cols; ++j ) {
|
||||||
// Toss a coin, biased by the proba of being 1.
|
// Toss a coin, biased by the proba of being 1.
|
||||||
vec.push_back( rng.flip( distrib(i,j) ) );
|
if( rng.flip( distrib(i,j) ) ) {
|
||||||
|
make_true( atom, i, j );
|
||||||
|
} else {
|
||||||
|
make_false( atom, i, j );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
solution.push_back( vec );
|
solution.push_back( atom );
|
||||||
}
|
}
|
||||||
|
|
||||||
return solution;
|
return solution;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue