[aGruM] removed exceptions when checking prior compatibilities. Fixed a bug in…

[aGruM] removed exceptions when checking prior compatibilities. Fixed a bug in message when conditionning set not found. Merged initial_structure and dag_for_parameterlearning in BNLearner
parent aca776e4
Pipeline #24149141 passed with stages
in 63 minutes 23 seconds
......@@ -832,7 +832,7 @@ namespace gum {
}
}
bool genericBNLearner::__checkScoreAprioriCompatibility() {
std::string genericBNLearner::checkScoreAprioriCompatibility() {
const std::string& apriori = __getAprioriType();
switch (__score_type) {
......@@ -856,8 +856,7 @@ namespace gum {
__apriori_weight);
default:
GUM_ERROR(OperationNotAllowed,
"genericBNLearner does not support yet this score");
return "genericBNLearner does not support yet this score";
}
}
......
......@@ -411,6 +411,11 @@ namespace gum {
/// use the Dirichlet apriori
void useAprioriDirichlet(const std::string& filename);
/// checks whether the current score and apriori are compatible
/** @returns a non empty string if the apriori is somehow compatible with the
* score.*/
std::string checkScoreAprioriCompatibility();
/// @}
// ##########################################################################
......@@ -608,28 +613,6 @@ namespace gum {
/// prepares the initial graph for 3off2 or miic
MixedGraph __prepare_miic_3off2();
/// checks whether the current score and apriori are compatible
/** @returns true if the apriori is compatible with the score.
* @throws IncompatibleScoreApriori is raised if the apriori is known to
* be incompatible with the score. Such a case usually arises because the
* score already implicitly contains an apriori which should not be
* combined
* with the apriori passed in argument. aGrUM will nevertheless allow you
* to
* use this apriori with the score, but you should be warned that the
* result
* of learning will most probably be meaningless.
* @throws PossiblyIncompatibleScoreApriori is raised if, in general, the
* apriori is incompatible with the score but, with its current weight, it
* becomes compatible (e.g., a Dirichlet apriori with a 0-weight is the
* same as a NoApriori). In such a case, you should not modify the weight.
* aGrUM will allow you to do so but the result of learning will most
* probably be meaningless.
* @throws InvalidArgument is raised if the apriori is not handled yet by
* method isAprioriCompatible (the method needs be updated to take it into
* account). */
bool __checkScoreAprioriCompatibility();
/// returns the type (as a string) of a given apriori
const std::string& __getAprioriType() const;
......
......@@ -100,37 +100,37 @@ namespace gum {
// indicate that we wish to use an AIC score
INLINE void genericBNLearner::useScoreAIC() {
__score_type = ScoreType::AIC;
__checkScoreAprioriCompatibility();
checkScoreAprioriCompatibility();
}
// indicate that we wish to use a BD score
INLINE void genericBNLearner::useScoreBD() {
__score_type = ScoreType::BD;
__checkScoreAprioriCompatibility();
checkScoreAprioriCompatibility();
}
// indicate that we wish to use a BDeu score
INLINE void genericBNLearner::useScoreBDeu() {
__score_type = ScoreType::BDeu;
__checkScoreAprioriCompatibility();
checkScoreAprioriCompatibility();
}
// indicate that we wish to use a BIC score
INLINE void genericBNLearner::useScoreBIC() {
__score_type = ScoreType::BIC;
__checkScoreAprioriCompatibility();
checkScoreAprioriCompatibility();
}
// indicate that we wish to use a K2 score
INLINE void genericBNLearner::useScoreK2() {
__score_type = ScoreType::K2;
__checkScoreAprioriCompatibility();
checkScoreAprioriCompatibility();
}
// indicate that we wish to use a Log2Likelihood score
INLINE void genericBNLearner::useScoreLog2Likelihood() {
__score_type = ScoreType::LOG2LIKELIHOOD;
__checkScoreAprioriCompatibility();
checkScoreAprioriCompatibility();
}
// sets the max indegree
......@@ -304,13 +304,13 @@ namespace gum {
}
__apriori_weight = weight;
__checkScoreAprioriCompatibility();
checkScoreAprioriCompatibility();
}
// use the apriori smoothing
INLINE void genericBNLearner::useNoApriori() {
__apriori_type = AprioriType::NO_APRIORI;
__checkScoreAprioriCompatibility();
checkScoreAprioriCompatibility();
}
// use the apriori smoothing
......@@ -319,7 +319,7 @@ namespace gum {
if (weight >= 0) { setAprioriWeight(weight); }
__checkScoreAprioriCompatibility();
checkScoreAprioriCompatibility();
}
// use the Dirichlet apriori
......@@ -327,7 +327,7 @@ namespace gum {
genericBNLearner::useAprioriDirichlet(const std::string& filename) {
__apriori_dbname = filename;
__apriori_type = AprioriType::DIRICHLET_FROM_DATABASE;
__checkScoreAprioriCompatibility();
checkScoreAprioriCompatibility();
}
// returns the type (as a string) of a given apriori
......
......@@ -173,9 +173,6 @@ namespace gum {
NodeProperty< Sequence< std::string > >
__labelsFromBN(const std::string& filename,
const BayesNet< GUM_SCALAR >& src);
// patch for learnParameters(bool take_into_account_score );
DAG __dag4learnParams;
};
} /* namespace learning */
......
......@@ -56,24 +56,22 @@ namespace gum {
const std::string& filename,
const gum::BayesNet< GUM_SCALAR >& bn,
const std::vector< std::string >& missing_symbols) :
genericBNLearner(filename, bn, missing_symbols)
, __dag4learnParams (bn.dag() ) {
genericBNLearner(filename, bn, missing_symbols) {
setInitialDAG(bn.dag());
GUM_CONSTRUCTOR(BNLearner)
}
/// copy constructor
template < typename GUM_SCALAR >
BNLearner< GUM_SCALAR >::BNLearner(const BNLearner< GUM_SCALAR >& src) :
genericBNLearner(src),
__dag4learnParams ( src.__dag4learnParams ) {
genericBNLearner(src) {
GUM_CONSTRUCTOR(BNLearner);
}
/// move constructor
template < typename GUM_SCALAR >
BNLearner< GUM_SCALAR >::BNLearner(BNLearner< GUM_SCALAR >&& src) :
genericBNLearner(src),
__dag4learnParams ( src.__dag4learnParams ) {
genericBNLearner(src) {
GUM_CONSTRUCTOR(BNLearner);
}
......@@ -95,7 +93,6 @@ namespace gum {
BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::
operator=(const BNLearner< GUM_SCALAR >& src) {
genericBNLearner::operator=(src);
__dag4learnParams = src.__dag4learnParams;
return *this;
}
......@@ -104,7 +101,6 @@ namespace gum {
BNLearner< GUM_SCALAR >& BNLearner< GUM_SCALAR >::
operator=(BNLearner< GUM_SCALAR >&& src) {
genericBNLearner::operator=(std::move(src));
__dag4learnParams = src.__dag4learnParams;
return *this;
}
......@@ -112,6 +108,10 @@ namespace gum {
template < typename GUM_SCALAR >
BayesNet< GUM_SCALAR > BNLearner< GUM_SCALAR >::learnBN() {
// create the score, the apriori and the estimator
auto notification = checkScoreAprioriCompatibility();
if (notification != "") {
std::cout << "[aGrUM notification] " << notification << std::endl;
}
__createApriori();
__createScore();
__createParamEstimator();
......@@ -131,33 +131,34 @@ namespace gum {
BNLearner< GUM_SCALAR >::learnParameters(const DAG& dag,
bool take_into_account_score) {
// if the dag contains no node, return an empty BN
if ( ! dag.size() )
return BayesNet< GUM_SCALAR > ();
if (dag.size()==0) return BayesNet< GUM_SCALAR >();
// check that the dag corresponds to the database
std::vector<NodeId> ids;
ids.reserve ( dag.sizeNodes() );
for ( const auto node : dag ) ids.push_back ( node );
std::sort ( ids.begin(), ids.end() );
std::vector< NodeId > ids;
ids.reserve(dag.sizeNodes());
for (const auto node : dag)
ids.push_back(node);
std::sort(ids.begin(), ids.end());
if ( ids.back() >= __score_database.names().size () ) {
if (ids.back() >= __score_database.names().size()) {
std::stringstream str;
str << "Learning parameters corresponding to the dag is impossible "
<< "because the database does not contain the following nodeID";
std::vector<NodeId> bad_ids;
for ( const auto node : ids ) {
if ( node >= __score_database.names().size () )
bad_ids.push_back ( node );
std::vector< NodeId > bad_ids;
for (const auto node : ids) {
if (node >= __score_database.names().size()) bad_ids.push_back(node);
}
if ( bad_ids.size() > 1 ) str << 's';
if (bad_ids.size() > 1) str << 's';
str << ": ";
bool deja = false;
for ( const auto node : bad_ids ) {
if ( deja ) str << ", ";
else deja = true;
for (const auto node : bad_ids) {
if (deja)
str << ", ";
else
deja = true;
str << node;
}
GUM_ERROR ( MissingVariableInDatabase, str.str() );
GUM_ERROR(MissingVariableInDatabase, str.str());
}
// create the apriori and the estimator
......@@ -173,14 +174,14 @@ namespace gum {
__score_database.databaseTable().translatorSet());
}
/// learns a BN (its parameters) when its structure is known
template < typename GUM_SCALAR >
BayesNet< GUM_SCALAR >
BNLearner< GUM_SCALAR >::learnParameters(bool take_into_account_score) {
return learnParameters( __dag4learnParams, take_into_account_score );
return learnParameters(__initial_dag, take_into_account_score);
}
template < typename GUM_SCALAR >
NodeProperty< Sequence< std::string > >
......
......@@ -111,7 +111,7 @@ namespace gum {
* follows:
* first, there are the conditioning nodes (in the order in which they
* were specified) and, then, the target node.
* @throw CPTError is raised if some values of the conditioning sets were
* @throw DatabaseError is raised if some values of the conditioning sets were
* not observed in the database. */
const std::vector< double, CountAlloc >& parameters(Idx nodeset_index);
......
......@@ -92,7 +92,7 @@ namespace gum {
const std::vector< Idx, IdSetAlloc >* conditioning_nodes =
this->_getConditioningNodes(nodeset_index);
const auto& modals = this->modalities();
const Idx target_modal = modals[all_nodes[all_nodes.size() - 1]];
const Idx target_modal = modals[all_nodes[all_nodes.size() - 1]];
std::vector< double, CountAlloc >& N_ijk =
const_cast< std::vector< double, CountAlloc >& >(
this->_getAllCounts(nodeset_index));
......@@ -117,39 +117,43 @@ namespace gum {
// check that all conditioning nodes have strictly positive counts
for (Idx j = 0; j < conditioning_size; ++j) {
if (N_ij[j] + N_prime_ij[j] == 0) {
const std::size_t cond_nb = conditioning_nodes->size ();
std::vector<Idx> offsets ( cond_nb );
Idx offset = 1;
std::size_t i;
for ( i = std::size_t(0); i < cond_nb; ++i ) {
const std::size_t cond_nb = conditioning_nodes->size();
std::vector< Idx > offsets(cond_nb);
Idx offset = 1;
std::size_t i;
for (i = std::size_t(0); i < cond_nb; ++i) {
offsets[i] = offset;
offset *= modals[conditioning_nodes->operator[](i)];
}
std::vector<Idx> values ( cond_nb );
std::vector< Idx > values(cond_nb);
i = 0;
offset = j;
for ( Idx jj = cond_nb - 1; i < cond_nb; ++i, --j ) {
for (Idx jj = cond_nb - 1; i < cond_nb; ++i, --jj) {
values[jj] = offset / offsets[jj];
offset %= offsets[jj];
}
//const DatabaseTable<>& da
// const DatabaseTable<>& da
std::stringstream str;
str << "The conditioning set <";
bool deja = false;
for ( i = std::size_t(0); i < cond_nb; ++i ) {
if ( deja ) str << ", ";
else deja = true;
for (i = std::size_t(0); i < cond_nb; ++i) {
if (deja)
str << ", ";
else
deja = true;
auto id = conditioning_nodes->operator[](i);
const DiscreteVariable& var =
dynamic_cast<const DiscreteVariable&> ( this->_database->variable(id) );
const DiscreteVariable& var =
dynamic_cast< const DiscreteVariable& >(
this->_database->variable(id));
str << var.name() << "=" << var.labels()[values[i]];
}
auto id = all_nodes[all_nodes.size() - 1];
auto id = all_nodes[all_nodes.size() - 1];
const Variable& var = this->_database->variable(id);
str << "> for target node " << var.name()
<< " never appears in the database";
GUM_ERROR(CPTError, str.str());
<< " never appears in the database. Please consider using "
"priors such as smoothing.";
GUM_ERROR(DatabaseError, str.str());
}
}
......@@ -163,38 +167,42 @@ namespace gum {
// check that all conditioning nodes have strictly positive counts
for (Idx j = 0; j < conditioning_size; ++j) {
if (!N_ij[j]) {
const std::size_t cond_nb = conditioning_nodes->size ();
std::vector<Idx> offsets ( cond_nb );
Idx offset = 1;
std::size_t i;
for ( i = std::size_t(0); i < cond_nb; ++i ) {
const std::size_t cond_nb = conditioning_nodes->size();
std::vector< Idx > offsets(cond_nb);
Idx offset = 1;
std::size_t i;
for (i = std::size_t(0); i < cond_nb; ++i) {
offsets[i] = offset;
offset *= modals[conditioning_nodes->operator[](i)];
}
std::vector<Idx> values ( cond_nb );
std::vector< Idx > values(cond_nb);
i = 0;
offset = j;
for ( Idx jj = cond_nb - 1; i < cond_nb; ++i, --j ) {
for (Idx jj = cond_nb - 1; i < cond_nb; ++i, --jj) {
values[jj] = offset / offsets[jj];
offset %= offsets[jj];
}
std::stringstream str;
str << "The conditioning set <";
bool deja = true;
for ( i = std::size_t(0); i < cond_nb; ++i ) {
if ( deja ) str << ", ";
else deja = true;
for (i = std::size_t(0); i < cond_nb; ++i) {
if (deja)
str << ", ";
else
deja = true;
auto id = conditioning_nodes->operator[](i);
const DiscreteVariable& var =
dynamic_cast<const DiscreteVariable&> ( this->_database->variable(id) );
const DiscreteVariable& var =
dynamic_cast< const DiscreteVariable& >(
this->_database->variable(id));
str << var.name() << "=" << var.labels()[values[i]];
}
auto id = all_nodes[all_nodes.size() - 1];
auto id = all_nodes[all_nodes.size() - 1];
const Variable& var = this->_database->variable(id);
str << "> for target node " << var.name()
<< " never appears in the database";
GUM_ERROR(CPTError, str.str());
<< " never appears in the database. Please consider using "
"priors such as smoothing.";
GUM_ERROR(DatabaseError, str.str());
}
}
......@@ -222,7 +230,7 @@ namespace gum {
N_ijk[k] = (N_ijk[k] + N_prime_ijk[k]) / sum;
}
} else {
GUM_ERROR(CPTError,
GUM_ERROR(DatabaseError,
"The database being empty, it is impossible "
"to estimate the parameters by maximum likelihood");
}
......@@ -237,7 +245,7 @@ namespace gum {
N_ijk[k] /= sum;
}
} else {
GUM_ERROR(CPTError,
GUM_ERROR(DatabaseError,
"The database being empty, it is impossible "
"to estimate the parameters by maximum likelihood");
}
......
......@@ -163,10 +163,10 @@ namespace gum {
* instance, adding a Dirichlet apriori to the K2 score is not very
* meaningful since K2 corresonds to a BD score with a 1-smoothing
* apriori.
* aGrUM allows you to perform such combination, but yuou can check with
* aGrUM allows you to perform such combination, but you can check with
* method isAprioriCompatible () whether the result the score will give
* you is meaningful or not. */
virtual bool isAprioriCompatible() const = 0;
virtual std::string isAprioriCompatible() const = 0;
/// returns the internal apriori of the score
/** Some scores include an apriori. For instance, the K2 score is a BD
......
......@@ -111,70 +111,21 @@ namespace gum {
/// indicates whether the apriori is compatible (meaningful) with the
/// score
/** @returns true if the apriori is compatible with the score.
* @throws IncompatibleScoreApriori is raised if the apriori is known to
* be incompatible with the score. Such a case arises because the score
* already implicitly contains an apriori which should not be combined
* with the apriori passed in argument. aGrUM will nevertheless allow you
* to
* use this apriori with the score, but you should be warned that the
* result
* of learning will most probably be meaningless.
* @throws PossiblyIncompatibleScoreApriori is raised if, in general, the
* apriori is incompatible with the score but, with its current weight, it
* becomes compatible (e.g., a Dirichlet apriori with a 0-weight is the
* same as a NoApriori). In such a case, you should not modify the weight.
* aGrUM will allow you to do so but the result of learning will most
* probably be meaningless.
* @throws InvalidArgument is raised if the apriori is not handled yet by
* method isAprioriCompatible (the method needs be updated to take it into
* account). */
virtual bool isAprioriCompatible() const final;
/** @returns a non empty string if the apriori is compatible with the
* score.*/
virtual std::string isAprioriCompatible() const final;
/// indicates whether the apriori is compatible (meaningful) with the
/// score
/** @returns true if the apriori is compatible with the score.
* @throws IncompatibleScoreApriori is raised if the apriori is known to
* be incompatible with the score. Such a case arises because the score
* already implicitly contains an apriori which should not be combined
* with the apriori passed in argument. aGrUM will nevertheless allow you
* to
* use this apriori with the score, but you should be warned that the
* result
* of learning will most probably be meaningless.
* @throws PossiblyIncompatibleScoreApriori is raised if, in general, the
* apriori is incompatible with the score but, with its current weight, it
* becomes compatible (e.g., a Dirichlet apriori with a 0-weight is the
* same as a NoApriori). In such a case, you should not modify the weight.
* aGrUM will allow you to do so but the result of learning will most
* probably be meaningless.
* @throws InvalidArgument is raised if the apriori is not handled yet by
* method isAprioriCompatible (the method needs be updated to take it into
* account). */
static bool isAprioriCompatible(const std::string& apriori_type,
double weight = 1.0f);
/** @returns a non empty string if the apriori is compatible with the score.
*/
static std::string isAprioriCompatible(const std::string& apriori_type,
double weight = 1.0f);
/// indicates whether the apriori is compatible (meaningful) with the
/// score
/** @returns true if the apriori is compatible with the score.
* @throws IncompatibleScoreApriori is raised if the apriori is known to
* be incompatible with the score. Such a case arises because the score
* already implicitly contains an apriori which should not be combined
* with the apriori passed in argument. aGrUM will nevertheless allow you
* to
* use this apriori with the score, but you should be warned that the
* result
* of learning will most probably be meaningless.
* @throws PossiblyIncompatibleScoreApriori is raised if, in general, the
* apriori is incompatible with the score but, with its current weight, it
* becomes compatible (e.g., a Dirichlet apriori with a 0-weight is the
* same as a NoApriori). In such a case, you should not modify the weight.
* aGrUM will allow you to do so but the result of learning will most
* probably be meaningless.
* @throws InvalidArgument is raised if the apriori is not handled yet by
* method isAprioriCompatible (the method needs be updated to take it into
* account). */
static bool
/** a non empty string if the apriori is compatible with the score. */
static std::string
isAprioriCompatible(const Apriori< IdSetAlloc, CountAlloc >& apriori);
/// returns the internal apriori of the score
......
......@@ -83,32 +83,32 @@ namespace gum {
/// indicates whether the apriori is compatible (meaningful) with the score
template < typename IdSetAlloc, typename CountAlloc >
bool ScoreAIC< IdSetAlloc, CountAlloc >::isAprioriCompatible(
std::string ScoreAIC< IdSetAlloc, CountAlloc >::isAprioriCompatible(
const std::string& apriori_type, double weight) {
// check that the apriori is compatible with the score
if ((apriori_type == AprioriDirichletType::type)
|| (apriori_type == AprioriSmoothingType::type)
|| (apriori_type == AprioriNoAprioriType::type)) {
return true;
return "";
}
// apriori types unsupported by the type checker
std::stringstream msg;
msg << "The apriori '" << apriori_type
<< "' is not yet supported by method isAprioriCompatible";
GUM_ERROR(InvalidArgument, msg.str());
return msg.str();
}
/// indicates whether the apriori is compatible (meaningful) with the score
template < typename IdSetAlloc, typename CountAlloc >
INLINE bool ScoreAIC< IdSetAlloc, CountAlloc >::isAprioriCompatible(
INLINE std::string ScoreAIC< IdSetAlloc, CountAlloc >::isAprioriCompatible(
const Apriori< IdSetAlloc, CountAlloc >& apriori) {
return isAprioriCompatible(apriori.getType(), apriori.weight());
}
/// indicates whether the apriori is compatible (meaningful) with the score
template < typename IdSetAlloc, typename CountAlloc >
INLINE bool ScoreAIC< IdSetAlloc, CountAlloc >::isAprioriCompatible() const {
INLINE std::string ScoreAIC< IdSetAlloc, CountAlloc >::isAprioriCompatible() const {
return isAprioriCompatible(*this->_apriori);
}
......
......@@ -113,67 +113,22 @@ namespace gum {
/// indicates whether the apriori is compatible (meaningful) with the
/// score
/** @returns true if the apriori is compatible with the score.
* @throws IncompatibleScoreApriori is raised if the apriori is known to
* be incompatible with the score. Such a case arises because the score
* needs an apriori and none is passed in argument. aGrUM will
* nevertheless
* allow you to use this apriori with the score, but the learning will
* certainly fail.
* @throws PossiblyIncompatibleScoreApriori is raised if the apriori with
* its current weight is compatible with the score but this may not be the
* case any more if you change the weight (e.g., if you put the weight of
* the apriori to 0, the latter will inevitably becomes incompatible).
* In such a case, you should not modify the weight. aGrUM will
* nevertheless
* allow you to do so but the result of learning may become meaningless.
* @throws InvalidArgument is raised if the apriori is not handled yet by
* method isAprioriCompatible (the method needs be updated to take it into
* account). */
virtual bool isAprioriCompatible() const final;
/** @returns a non empty string if the apriori is compatible with the
* score.*/
virtual std::string isAprioriCompatible() const final;
/// indicates whether the apriori is compatible (meaningful) with the
/// score
/** @returns true if the apriori is compatible with the score.
* @throws IncompatibleScoreApriori is raised if the apriori is known to
* be incompatible with the score. Such a case arises because the score
* needs an apriori and none is passed in argument. aGrUM will
* nevertheless
* allow you to use this apriori with the score, but the learning will
* certainly fail.
* @throws PossiblyIncompatibleScoreApriori is raised if the apriori with
* its current weight is compatible with the score but this may not be the
* case any more if you change the weight (e.g., if you put the weight of
* the apriori to 0, the latter will inevitably becomes incompatible).
* In such a case, you should not modify the weight. aGrUM will
* nevertheless
* allow you to do so but the result of learning may become meaningless.
* @throws InvalidArgument is raised if the apriori is not handled yet by
* method isAprioriCompatible (the method needs be updated to take it into
* account). */
static bool isAprioriCompatible(const std::string& apriori_type,
double weight = 1.0f);
/** @returns a non empty string if the apriori is compatible with the
* score.*/
static std::string isAprioriCompatible(const std::string& apriori_type,
double weight = 1.0f);
/// indicates whether the apriori is compatible (meaningful) with the
/// score
/** @returns true if the apriori is compatible with the score.
* @throws IncompatibleScoreApriori is raised if the apriori is known to
* be incompatible with the score. Such a case arises because the score
* needs an apriori and none is passed in argument. aGrUM will
* nevertheless
* allow you to use this apriori with the score, but the learning will
* certainly fail.
* @throws PossiblyIncompatibleScoreApriori is raised if the apriori with
* its current weight is compatible with the score but this may not be the
* case any more if you change the weight (e.g., if you put the weight of
* the apriori to 0, the latter will inevitably becomes incompatible).
* In such a case, you should not modify the weight. aGrUM will
* nevertheless
* allow you to do so but the result of learning may become meaningless.
* @throws InvalidArgument is raised if the apriori is not handled yet by
* method isAprioriCompatible (the method needs be updated to take it into
* account). */
static bool
/** @returns a non empty string if the apriori is compatible with the
* score.*/
static std::string
isAprioriCompatible(const Apriori< IdSetAlloc, CountAlloc >& apriori);
/// returns the internal apriori of the score
......
......@@ -85,35 +85,35 @@ namespace gum {
/// indicates whether the apriori is compatible (meaningful) with the score
template < typename IdSetAlloc, typename CountAlloc >
bool ScoreBD< IdSetAlloc, CountAlloc >::isAprioriCompatible(
std::string ScoreBD< IdSetAlloc, CountAlloc >::isAprioriCompatible(
const std::string& apriori_type, double weight) {
if (apriori_type == AprioriNoAprioriType::type) {
GUM_ERROR(IncompatibleScoreApriori, "The BD score requires an apriori");
return "The BD score requires an apriori";
}
if (weight != 0) {
GUM_ERROR(PossiblyIncompatibleScoreApriori,
"The apriori is currently compatible with the BD score but if "
"you change the weight, it may become incompatible");
return "The apriori is currently compatible with the BD score but if "
"you change the weight, it may become incompatible";
}
// apriori types unsupported by the type checker
std::stringstream msg;
msg << "The apriori '" << apriori_type
<< "' is not yet supported by method isAprioriCompatible";
GUM_ERROR(InvalidArgument, msg.str());
return msg.str();
}
/// indicates whether the apriori is compatible (meaningful) with the score
template < typename IdSetAlloc, typename CountAlloc >
INLINE bool ScoreBD< IdSetAlloc, CountAlloc >::isAprioriCompatible(
INLINE std::string ScoreBD< IdSetAlloc, CountAlloc >::isAprioriCompatible(
const Apriori< IdSetAlloc, CountAlloc >& apriori) {
return isAprioriCompatible(apriori.getType(), apriori.weight());
}
/// indicates whether the apriori is compatible (meaningful) with the score
template < typename IdSetAlloc, typename CountAlloc >
INLINE bool ScoreBD< IdSetAlloc, CountAlloc >::isAprioriCompatible() const {