Commit ce5d75bd by Pierre-Henri Wuillemin

merging with master

parents 5628af63 d34ffd85
Pipeline #13794180 passed with stage
in 4 minutes 56 seconds
......@@ -10,6 +10,7 @@ ColumnLimit: 83
MaxEmptyLinesToKeep: 2
IndentWidth: 2
ContinuationIndentWidth: 2
UseTab: Never
AccessModifierOffset: 0
......@@ -20,13 +21,14 @@ SpacesBeforeTrailingComments: 2
Cpp11BracedListStyle: true
BreakBeforeBraces: Attach
SpacesInParentheses: true
SpacesInParentheses: false
SpaceInEmptyParentheses: false
AlwaysBreakTemplateDeclarations: true
BreakBeforeBinaryOperators: NonAssignment
BreakConstructorInitializersBeforeComma: true
BreakBeforeBinaryOperators: false
SpacesInAngles: true
#clang-format-4.0
#BreakStringLiterals: true
......
......@@ -210,13 +210,13 @@ windows_aGrUM_build:
<<: *windows_template
stage: agrum
script:
- python act --no-fun install release aGrUM %ACT_OPTIONS% || python act --no-fun clean && python act --no-fun lib release aGrUM %ACT_OPTIONS%
- python act --no-fun install release aGrUM %ACT_OPTIONS% || python act --no-fun clean && python act --no-fun install release aGrUM %ACT_OPTIONS%
windows_pyAgrum_build:
<<: *windows_template
stage: pyagrum
script:
- python act --no-fun install release pyAgrum %ACT_OPTIONS% || python act --no-fun clean && python act --no-fun lib release pyAgrum %ACT_OPTIONS%
- python act --no-fun install release pyAgrum %ACT_OPTIONS% || python act --no-fun clean && python act --no-fun install release pyAgrum %ACT_OPTIONS%
windows_aGrUM_test:
<<: *windows_template
......
......@@ -173,6 +173,7 @@ def getPost(current, target):
line = 'copy /Y "wrappers\pyAgrum\Release\_pyAgrum.pyd" "wrappers\pyAgrum\." & ' + cfg.python + " ..\\..\\wrappers\\pyAgrum\\testunits\\"+gumTest
else:
line = cfg.python + " ../../wrappers/pyAgrum/testunits/"+gumTest
line+=" "+current['mode']
return line, True
return "", False
......
......@@ -17,8 +17,8 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <agrum/agrum.h>
#include <agrum/BN/BayesNet.h>
#include <agrum/config.h>
template class gum::BayesNet<float>;
template class gum::BayesNet<double>;
......@@ -30,7 +30,7 @@
#include <utility>
#include <agrum/config.h>
#include <agrum/agrum.h>
#include <agrum/core/hashTable.h>
......@@ -79,7 +79,7 @@ namespace gum {
public:
/**
* Create a bn with a dotlike syntax : 'a->b->c;b->d;'. The domain size maybe
* specified using 'a[10]'. Note that if the dotlike string contains such a
* specified using 'a[10]' or using 'a{yes|maybe|no}'. Note that if the dotlike string contains such a
* specification for an already defined variable, the first specification will
* be used.
*
......
......@@ -27,7 +27,7 @@
#ifndef GUM_BAYES_NET_FRAGMENT_H
#define GUM_BAYES_NET_FRAGMENT_H
#include <agrum/config.h>
#include <agrum/agrum.h>
#include <agrum/BN/IBayesNet.h>
#include <agrum/graphs/parts/listeners/diGraphListener.h>
......
......@@ -29,7 +29,7 @@
#include <utility>
#include <agrum/config.h>
#include <agrum/agrum.h>
#include <agrum/core/hashTable.h>
......
......@@ -29,7 +29,7 @@
#include <utility>
#include <agrum/config.h>
#include <agrum/agrum.h>
#include <agrum/core/hashTable.h>
#include <agrum/core/list.h>
......
......@@ -28,7 +28,7 @@
#include <agrum/BN/BayesNet.h>
#include <agrum/config.h>
#include <agrum/agrum.h>
#include <agrum/graphs/DAG.h>
#include <agrum/graphs/cliqueGraph.h>
......
......@@ -29,7 +29,7 @@
#include <agrum/BN/IBayesNet.h>
#include <agrum/config.h>
#include <agrum/agrum.h>
namespace gum {
......
/***************************************************************************
* Copyright (C) 2005 by Pierre-Henri WUILLEMIN et Christophe GONZALES *
* {prenom.nom}_at_lip6.fr *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/**
* @file
* @brief KL divergence between BNs with GIBBS implementation
*
* @author Pierre-Henri WUILLEMIN
*/
#include <agrum/BN/algorithms/divergence/GibbsKL.h>
#include <cmath>
......
......@@ -23,14 +23,16 @@
*GIBBS
*sampling
*
* @author Pierre-Henri WUILLEMIN
* @author Paul ALAM & Pierre-Henri WUILLEMIN
*
*/
#ifndef GUM_GIBBS_KL_H
#define GUM_GIBBS_KL_H
#ifndef GUM_GIBBS_KL2_H
#define GUM_GIBBS_KL2_H
#include <agrum/BN/algorithms/divergence/KL.h>
#include <agrum/BN/samplers/GibbsSampler.h>
#include <agrum/BN/inference/tools/gibbsOperator.h>
#include <agrum/core/approximations/approximationScheme.h>
#include <agrum/core/signal/signaler.h>
......@@ -38,42 +40,42 @@
namespace gum {
/**
* GibbsKL computes the KL divergence betweens 2 BNs using an approximation
*pattern
*: GIBBS sampling.
*
* KL.process() computes KL(P||Q) using klPQ() and KL(Q||P) using klQP(). The
*computations are made once. The second is for free :)
* GibbsKL allows as well to compute in the same time the Hellinger distance
*(\f$
*\sqrt{\sum_i (\sqrt{p_i}-\sqrt{q_i})^2}\f$) (Kokolakis and Nanopoulos, 2001)
* and Bhattacharya distance (Kaylath,T. 1967)
*
* It may happen that P*ln(P/Q) is not computable (Q=0 and P!=0). In such a
*case, KL
*keeps working but trace this error (errorPQ() and errorQP()). In those cases,
*Hellinger distance approximation is under-evaluated.
*
* @warning : convergence and stop criteria are designed w.r.t the main
*computation
*: KL(P||Q). The 3 others have no guarantee.
*
* snippets :
* @code
* gum::KL base_kl(net1,net2);
* if (base_kl.difficulty()!=KL::HEAVY) {
* gum::BruteForceKL kl(base_kl);
* std::cout<<"KL net1||net2 :"<<kl.klPQ()<<std::endl;
* } else {
* gum::GibbsKL kl(base_kl);
* std::cout<<"KL net1||net2 :"<<kl.klPQ()<<std::endl;
* }
* @endcode
*/
template <typename GUM_SCALAR>
class GibbsKL : public KL<GUM_SCALAR>,
* GibbsKL computes the KL divergence betweens 2 BNs using an approximation
*pattern: GIBBS sampling.
*
* KL.process() computes KL(P||Q) using klPQ() and KL(Q||P) using klQP(). The
*computations are made once. The second is for free :)
* GibbsKL allows as well to compute in the same time the Hellinger distance
*(\f$
*\sqrt{\sum_i (\sqrt{p_i}-\sqrt{q_i})^2}\f$) (Kokolakis and Nanopoulos, 2001)
* and Bhattacharya distance (Kaylath,T. 1967)
*
* It may happen that P*ln(P/Q) is not computable (Q=0 and P!=0). In such a
*case, KL
*keeps working but trace this error (errorPQ() and errorQP()). In those cases,
*Hellinger distance approximation is under-evaluated.
*
* @warning : convergence and stop criteria are designed w.r.t the main
*computation
*: KL(P||Q). The 3 others have no guarantee.
*
* snippets :
* @code
* gum::KL base_kl(net1,net2);
* if (base_kl.difficulty()!=KL::HEAVY) {
* gum::BruteForceKL kl(base_kl);
* std::cout<<"KL net1||net2 :"<<kl.klPQ()<<std::endl;
* } else {
* gum::GibbsKL2 kl(base_kl);
* std::cout<<"KL net1||net2 :"<<kl.klPQ()<<std::endl;
* }
* @endcode
*/
template < typename GUM_SCALAR >
class GibbsKL : public KL< GUM_SCALAR >,
public ApproximationScheme,
public samplers::GibbsSampler<GUM_SCALAR> {
public GibbsOperator< GUM_SCALAR > {
public:
/* no default constructor */
......@@ -82,42 +84,52 @@ namespace gum {
* or
* compatible node sets.
*/
GibbsKL( const IBayesNet<GUM_SCALAR>& P, const IBayesNet<GUM_SCALAR>& Q );
GibbsKL(const IBayesNet< GUM_SCALAR >& P, const IBayesNet< GUM_SCALAR >& Q);
/** copy constructor
*/
GibbsKL( const KL<GUM_SCALAR>& kl );
GibbsKL(const KL< GUM_SCALAR >& kl);
/** destructor */
~GibbsKL();
using samplers::GibbsSampler<GUM_SCALAR>::particle;
using samplers::GibbsSampler<GUM_SCALAR>::initParticle;
using samplers::GibbsSampler<GUM_SCALAR>::nextParticle;
using samplers::GibbsSampler<GUM_SCALAR>::bn;
/**
* @brief Number of burn in for one iteration.
* @param b The number of burn in.
* @throw OutOfLowerBound Raised if b < 1.
*/
void setBurnIn(Size b) { this->_burn_in = b; };
/**
* @brief Returns the number of burn in.
* @return Returns the number of burn in.
*/
Size burnIn(void) const { return this->_burn_in; };
protected:
void _computeKL( void );
void _computeKL(void);
using KL<GUM_SCALAR>::_p;
using KL<GUM_SCALAR>::_q;
using KL<GUM_SCALAR>::_hellinger;
using KL<GUM_SCALAR>::_bhattacharya;
using KL< GUM_SCALAR >::_p;
using KL< GUM_SCALAR >::_q;
using KL< GUM_SCALAR >::_hellinger;
using KL< GUM_SCALAR >::_bhattacharya;
using KL<GUM_SCALAR>::_klPQ;
using KL<GUM_SCALAR>::_klQP;
using KL< GUM_SCALAR >::_klPQ;
using KL< GUM_SCALAR >::_klQP;
using KL<GUM_SCALAR>::_errorPQ;
using KL<GUM_SCALAR>::_errorQP;
using KL< GUM_SCALAR >::_errorPQ;
using KL< GUM_SCALAR >::_errorQP;
};
extern template class GibbsKL<float>;
extern template class GibbsKL<double>;
extern template class GibbsKL< float >;
extern template class GibbsKL< double >;
} // namespace gum
#include <agrum/BN/algorithms/divergence/GibbsKL_tpl.h>
#endif // GUM_GIBBS_KL_H
#endif
......@@ -21,83 +21,98 @@
* @file
* @brief KL divergence between BNs -- implementation using Gibbs sampling
*
* @author Pierre-Henri WUILLEMIN
* @author Paul ALAM & Pierre-Henri WUILLEMIN
*/
#include <cmath>
#include <agrum/BN/IBayesNet.h>
#include <agrum/core/hashTable.h>
#include <agrum/BN/algorithms/divergence/GibbsKL.h>
#include <agrum/BN/samplers/GibbsSampler.h>
#include <agrum/BN/inference/tools/gibbsOperator.h>
#include <agrum/core/approximations/approximationScheme.h>
#include <agrum/core/hashTable.h>
#include <cmath>
#define KL_DEFAULT_MAXITER 10000000
#define KL_DEFAULT_EPSILON 1e-10
#define KL_DEFAULT_MIN_EPSILON_RATE 1e-10
#define KL_DEFAULT_PERIOD_SIZE 500
#define KL_DEFAULT_VERBOSITY false
#define KL_DEFAULT_BURNIN 3000
#define GIBBSKL_DEFAULT_MAXITER 10000000
#define GIBBSKL_DEFAULT_EPSILON 1e-10
#define GIBBSKL_DEFAULT_MIN_EPSILON_RATE 1e-10
#define GIBBSKL_DEFAULT_PERIOD_SIZE 200
#define GIBBSKL_DEFAULT_VERBOSITY false
#define GIBBSKL_DEFAULT_BURNIN 2000
#define GIBBSKL_DEFAULT_TIMEOUT 6000
#define GIBBSKL_POURCENT_DRAWN_SAMPLE 10 // percent drawn
#define GIBBSKL_DRAWN_AT_RANDOM false
namespace gum {
template <typename GUM_SCALAR>
GibbsKL<GUM_SCALAR>::GibbsKL( const IBayesNet<GUM_SCALAR>& P,
const IBayesNet<GUM_SCALAR>& Q )
: KL<GUM_SCALAR>( P, Q )
template < typename GUM_SCALAR >
GibbsKL< GUM_SCALAR >::GibbsKL(const IBayesNet< GUM_SCALAR >& P,
const IBayesNet< GUM_SCALAR >& Q)
: KL< GUM_SCALAR >(P, Q)
, ApproximationScheme()
, samplers::GibbsSampler<GUM_SCALAR>( P ) {
GUM_CONSTRUCTOR( GibbsKL );
setEpsilon( KL_DEFAULT_EPSILON );
setMinEpsilonRate( KL_DEFAULT_MIN_EPSILON_RATE );
setMaxIter( KL_DEFAULT_MAXITER );
setVerbosity( KL_DEFAULT_VERBOSITY );
setBurnIn( KL_DEFAULT_BURNIN );
setPeriodSize( KL_DEFAULT_PERIOD_SIZE );
, GibbsOperator< GUM_SCALAR >(
P,
nullptr,
1 + (P.size() * GIBBSKL_POURCENT_DRAWN_SAMPLE / 100),
GIBBSKL_DRAWN_AT_RANDOM) {
GUM_CONSTRUCTOR(GibbsKL);
setEpsilon(GIBBSKL_DEFAULT_EPSILON);
setMinEpsilonRate(GIBBSKL_DEFAULT_MIN_EPSILON_RATE);
setMaxIter(GIBBSKL_DEFAULT_MAXITER);
setVerbosity(GIBBSKL_DEFAULT_VERBOSITY);
setBurnIn(GIBBSKL_DEFAULT_BURNIN);
setPeriodSize(GIBBSKL_DEFAULT_PERIOD_SIZE);
setMaxTime(GIBBSKL_DEFAULT_TIMEOUT);
}
template <typename GUM_SCALAR>
GibbsKL<GUM_SCALAR>::GibbsKL( const KL<GUM_SCALAR>& kl )
: KL<GUM_SCALAR>( kl )
template < typename GUM_SCALAR >
GibbsKL< GUM_SCALAR >::GibbsKL(const KL< GUM_SCALAR >& kl)
: KL< GUM_SCALAR >(kl)
, ApproximationScheme()
, samplers::GibbsSampler<GUM_SCALAR>( kl.p() ) {
GUM_CONSTRUCTOR( GibbsKL );
setEpsilon( KL_DEFAULT_EPSILON );
setMinEpsilonRate( KL_DEFAULT_MIN_EPSILON_RATE );
setMaxIter( KL_DEFAULT_MAXITER );
setVerbosity( KL_DEFAULT_VERBOSITY );
setBurnIn( KL_DEFAULT_BURNIN );
setPeriodSize( KL_DEFAULT_PERIOD_SIZE );
// Gibbs operator with 10% of nodes changes at random between each samples
, GibbsOperator< GUM_SCALAR >(
kl.p(),
nullptr,
1 + (kl.p().size() * GIBBSKL_POURCENT_DRAWN_SAMPLE / 100),
true) {
GUM_CONSTRUCTOR(GibbsKL);
setEpsilon(GIBBSKL_DEFAULT_EPSILON);
setMinEpsilonRate(GIBBSKL_DEFAULT_MIN_EPSILON_RATE);
setMaxIter(GIBBSKL_DEFAULT_MAXITER);
setVerbosity(GIBBSKL_DEFAULT_VERBOSITY);
setBurnIn(GIBBSKL_DEFAULT_BURNIN);
setPeriodSize(GIBBSKL_DEFAULT_PERIOD_SIZE);
setMaxTime(GIBBSKL_DEFAULT_TIMEOUT);
}
template <typename GUM_SCALAR>
GibbsKL<GUM_SCALAR>::~GibbsKL() {
GUM_DESTRUCTOR( GibbsKL );
template < typename GUM_SCALAR >
GibbsKL< GUM_SCALAR >::~GibbsKL() {
GUM_DESTRUCTOR(GibbsKL);
}
template <typename GUM_SCALAR>
void GibbsKL<GUM_SCALAR>::_computeKL() {
template < typename GUM_SCALAR >
void GibbsKL< GUM_SCALAR >::_computeKL() {
gum::Instantiation Iq;
_q.completeInstantiation( Iq );
_q.completeInstantiation(Iq);
initParticle();
gum::Instantiation I = this->monteCarloSample();
initApproximationScheme();
// map between particle() variables and _q variables (using name of vars)
HashTable<const DiscreteVariable*, const DiscreteVariable*> map;
HashTable< const DiscreteVariable*, const DiscreteVariable* > map;
for ( Idx ite = 0; ite < particle().nbrDim(); ++ite ) {
map.insert( &particle().variable( ite ),
&_q.variableFromName( particle().variable( ite ).name() ) );
for (Idx ite = 0; ite < I.nbrDim(); ++ite) {
map.insert(&I.variable(ite), &_q.variableFromName(I.variable(ite).name()));
}
// BURN IN
for ( Idx i = 0; i < burnIn(); i++ )
nextParticle();
for (Idx i = 0; i < burnIn(); i++)
I = this->nextSample(I);
// SAMPLING
_klPQ = _klQP = _hellinger = (GUM_SCALAR)0.0;
......@@ -109,56 +124,54 @@ namespace gum {
GUM_SCALAR pp, pq;
do {
/// check_rate=false;
this->disableMinEpsilonRate(); // replace check_rate = false
nextParticle();
this->disableMinEpsilonRate();
I = this->nextSample(I);
updateApproximationScheme();
//_p.synchroInstantiations( Ip,particle() );
Iq.setValsFrom( map, particle() );
//_p.synchroInstantiations( Ip,I);
Iq.setValsFrom(map, I);
pp = _p.jointProbability( particle() );
pq = _q.jointProbability( Iq );
pp = _p.jointProbability(I);
pq = _q.jointProbability(Iq);
if ( pp != (GUM_SCALAR)0.0 ) {
_hellinger += std::pow( std::sqrt( pp ) - std::sqrt( pq ), 2 ) / pp;
if (pp != (GUM_SCALAR)0.0) {
_hellinger += std::pow(std::sqrt(pp) - std::sqrt(pq), 2) / pp;
if ( pq != (GUM_SCALAR)0.0 ) {
_bhattacharya += std::sqrt( pq / pp ); // std::sqrt(pp*pq)/pp
if (pq != (GUM_SCALAR)0.0) {
_bhattacharya += std::sqrt(pq / pp); // std::sqrt(pp*pq)/pp
/// check_rate=true;
this->enableMinEpsilonRate(); // replace check_rate=true;
ratio = pq / pp;
delta = (GUM_SCALAR)log2( ratio );
delta = (GUM_SCALAR)log2(ratio);
_klPQ += delta;
} else {
_errorPQ++;
}
}
if ( pq != (GUM_SCALAR)0.0 ) {
if ( pp != (GUM_SCALAR)0.0 ) {
if (pq != (GUM_SCALAR)0.0) {
if (pp != (GUM_SCALAR)0.0) {
// if we are here, it is certain that delta and ratio have been
// computed
// further lines above. (for now #112-113)
_klQP += ( GUM_SCALAR )( -delta * ratio );
_klQP += (GUM_SCALAR)(-delta * ratio);
} else {
_errorQP++;
}
}
if ( this->isEnabledMinEpsilonRate() /* replace check_rate */ ) {
if (this->isEnabledMinEpsilonRate()) { // replace check_rate
// delta is used as a temporary variable
delta = _klPQ / nbrIterations();
error = (GUM_SCALAR)std::abs( delta - oldPQ );
error = (GUM_SCALAR)std::abs(delta - oldPQ);
oldPQ = delta;
}
} while ( continueApproximationScheme( error /*,check_rate*/ ) );
} while (continueApproximationScheme(error)); //
_klPQ = -_klPQ / ( nbrIterations() );
_klQP = -_klQP / ( nbrIterations() );
_hellinger = std::sqrt( _hellinger / nbrIterations() );
_bhattacharya = -std::log( _bhattacharya );
_klPQ = -_klPQ / (nbrIterations());
_klQP = -_klQP / (nbrIterations());
_hellinger = std::sqrt(_hellinger / nbrIterations());
_bhattacharya = -std::log(_bhattacharya);
}
} // namespace gum
// kate: indent-mode cstyle; indent-width 2; replace-tabs on;
}
......@@ -36,7 +36,7 @@
#include <agrum/BN/BayesNet.h>
#include <agrum/BN/generator/simpleCPTGenerator.h>
#include <agrum/config.h>
#include <agrum/agrum.h>
#include <agrum/variables/labelizedVariable.h>
......
......@@ -28,7 +28,7 @@
#define GUM_I_CPT_DISTURBER_H
#include <agrum/BN/BayesNet.h>
#include <agrum/config.h>
#include <agrum/agrum.h>
#include <agrum/multidim/potential.h>
namespace gum {
......
......@@ -26,7 +26,7 @@
#ifndef GUM_I_CPT_GENERATOR_H
#define GUM_I_CPT_GENERATOR_H
#include <agrum/config.h>
#include <agrum/agrum.h>
#include <agrum/multidim/potential.h>
namespace gum {
......
......@@ -27,7 +27,7 @@
#ifndef GUM_MC_BAYES_NET_GENERATOR