Commit dda9d8e2 authored by Christophe Gonzales's avatar Christophe Gonzales

Merge branch 'master' into feature/learningNewDatabase

parents 8df58161 fa57fed0
......@@ -231,10 +231,13 @@ namespace gum {
* Given a sequence [var, p_1, p_2, ...,p_n-1, p_n] of parents, modalities
* are parsed in the given order (if all p_i are binary):
* \verbatim
* [0, 0, ..., 0, 0], [0, 0, ..., 0, 1],
* [0, 0, ..., 1, 0], [0, 0, ..., 1, 1],
* [0, 0, ..., 0, 0],
* [0, 0, ..., 0, 1],
* [0, 0, ..., 1, 0],
* [0, 0, ..., 1, 1],
* ...,
* [1, 1, ..., 1, 0], [1, 1, ..., 1, 1].
* [1, 1, ..., 1, 0],
* [1, 1, ..., 1, 1].
* \endverbatim
*
* @param variables the vector giving the order of parents
......
......@@ -168,6 +168,7 @@ void Parser::VARIABLE() {
void Parser::PROBA() {
Expect(16 /* "probability" */);
std::vector<std::string> var_seq;
std::string var;
std::vector<float> proba;
std::vector<std::string> parents;
......@@ -183,6 +184,14 @@ void Parser::PROBA() {
LISTE_PARENTS(parents);
}
Expect(19 /* ")" */);
for (Size i=Size(parents.size());i>=Size(1);--i){
TRY(factory().variableId(parents[i-1]));
TRY( factory().addParent(parents[i-1]));
}
var_seq.push_back(var);
for (Size i=0;i<Size(parents.size());++i){
var_seq.push_back(parents[i]);
}
TRY(factory().endParentsDeclaration());
Expect(7 /* "{" */);
while (la->kind == 23 /* "property" */) {
......@@ -196,7 +205,7 @@ void Parser::PROBA() {
TRY(s=factory().cptDomainSize(factory().variableId(var)));
if (proba.size()<s) Warning("Not enough data for cpt of node "+var);
if (proba.size()>s) Warning("Too many data for cpt of node "+var);
TRY(factory().rawConditionalTable(proba));
TRY(factory().rawConditionalTable(var_seq,proba));
TRY(factory().endRawProbabilityDeclaration());
}
......@@ -277,13 +286,13 @@ void Parser::IDENT_OR_INTEGER(std::string& name) {
void Parser::LISTE_PARENTS(std::vector<std::string>& parents ) {
std::string parent;
IDENT(parent);
TRY(factory().variableId(parent));
TRY( factory().addParent(parent));
parents.push_back(parent);
if (la->kind == 15 /* "," */) {
ExpectWeak(15 /* "," */, 2);
LISTE_PARENTS(parents);
while (la->kind == 15 /* "," */) {
Get();
IDENT(parent);
parents.push_back(parent);
}
}
......@@ -307,7 +316,7 @@ void Parser::LISTE_FLOAT(std::vector<float>& v ) {
float value;
FLOAT(value);
v.push_back(value);
if (StartOf(3)) {
if (StartOf(2)) {
if (la->kind == 15 /* "," */ || la->kind == 18 /* "|" */) {
if (la->kind == 15 /* "," */) {
Get();
......@@ -362,7 +371,7 @@ void Parser::LISTE_LABELS(const std::vector<std::string>& parents,std::vector<st
labels.push_back("*");
} else SynErr(33);
if (la->kind == 15 /* "," */) {
ExpectWeak(15 /* "," */, 4);
ExpectWeak(15 /* "," */, 3);
LISTE_LABELS(parents,labels,num_label+1);
}
}
......@@ -490,10 +499,9 @@ bool Parser::StartOf( int s ) {
const bool T = true;
const bool x = false;
static bool set[5][27] = {
static bool set[4][27] = {
{T,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x},
{T,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x},
{T,T,x,x, x,x,x,x, x,T,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x},
{x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,T, x,x,T,x, x,x,x,x, x,x,x},
{T,T,T,x, x,x,x,x, x,T,x,x, x,x,x,x, T,x,x,x, x,x,T,x, x,x,x}
};
......
......@@ -129,6 +129,7 @@ MODALITY_LIST = (. std::string label; .)
//==============
PROBA =
"probability" (.
std::vector<std::string> var_seq;
std::string var;
std::vector<float> proba;
std::vector<std::string> parents;
......@@ -139,7 +140,16 @@ PROBA =
TRY(factory().startParentsDeclaration(var));
.)
[ '|' LISTE_PARENTS<parents> ]
')' (. TRY(factory().endParentsDeclaration()); .)
')' (.
for (Size i=Size(parents.size());i>=Size(1);--i){
TRY(factory().variableId(parents[i-1]));
TRY( factory().addParent(parents[i-1]));
}
var_seq.push_back(var);
for (Size i=0;i<Size(parents.size());++i){
var_seq.push_back(parents[i]);
}
TRY(factory().endParentsDeclaration()); .)
'{'
{ PROPERTY }
(
......@@ -150,7 +160,7 @@ PROBA =
TRY(s=factory().cptDomainSize(factory().variableId(var)));
if (proba.size()<s) Warning("Not enough data for cpt of node "+var);
if (proba.size()>s) Warning("Too many data for cpt of node "+var);
TRY(factory().rawConditionalTable(proba));
TRY(factory().rawConditionalTable(var_seq,proba));
TRY(factory().endRawProbabilityDeclaration());
}
.)
......@@ -163,12 +173,13 @@ PROBA =
//==============
LISTE_PARENTS<. std::vector<std::string>& parents .> = (.std::string parent; .)
IDENT<parent> (.
TRY(factory().variableId(parent));
TRY( factory().addParent(parent));
parents.push_back(parent);
.)
[ WEAK ',' LISTE_PARENTS<parents> ]
IDENT<parent> (.
parents.push_back(parent);
.)
{ ',' IDENT<parent> (.
parents.push_back(parent);
.)
}
.
//==============
......
......@@ -284,11 +284,12 @@ void Parser::PARENTS_DEFINITION(std::string& name,std::vector<std::string>& var_
for (Size i=Size(parents.size());i>=Size(1);--i){
TRY(factory().variableId(parents[i-1]));
TRY(factory().addParent(parents[i-1]));
var_seq.push_back(parents[i-1]);
}
for(Size i=0;i<Size(parents.size());i++) {
/*for(Size i=0;i<Size(parents.size());i++) {
var_seq.push_back(parents[i]);
}
} */
}
}
......
......@@ -206,11 +206,12 @@ PARENTS_DEFINITION<.std::string& name,std::vector<std::string>& var_seq.> = (.st
for (Size i=Size(parents.size());i>=Size(1);--i){
TRY(factory().variableId(parents[i-1]));
TRY(factory().addParent(parents[i-1]));
var_seq.push_back(parents[i-1]);
}
for(Size i=0;i<Size(parents.size());i++) {
/*for(Size i=0;i<Size(parents.size());i++) {
var_seq.push_back(parents[i]);
}
} */
.)
]
]
......
......@@ -109,8 +109,8 @@ namespace gum {
std::stringstream str;
std::string tab = " "; // poor tabulation
Instantiation inst(cpt);
if (cpt.nbrDim() == 1) {
Instantiation inst(cpt);
str << "potential (" << cpt.variable(0).name() << ") {" << std::endl
<< tab << "data = ( ";
......@@ -118,59 +118,55 @@ namespace gum {
str << " " << cpt[inst];
}
str << ");" << std::endl << "}" << std::endl;
} else if (cpt.domainSize() > 1) {
// Instantiation inst( cpt );
Instantiation condVars; // Instantiation on the conditioning variables
str << ");";
} else { // cpt.domainSize() > 1
const Sequence< const DiscreteVariable* >& varsSeq = cpt.variablesSequence();
str << "potential ( " << (varsSeq[(Idx)0])->name() << " | ";
for (Idx i = 0; i < varsSeq.size(); i++) {
if (i != 0) str << varsSeq[i]->name() << " ";
Instantiation conds;
for (Idx i = 1; i < varsSeq.size(); i++)
conds.add(*varsSeq[i]);
condVars << *(varsSeq[i]);
}
str << "potential ( " << (varsSeq[(Idx)0])->name() << " | ";
for (Idx i = 1; i < varsSeq.size(); i++)
str << varsSeq[i]->name() << " ";
str << ") {" << std::endl << tab << "data = \n";
std::string comment;
conds.setFirst();
while (true) {
str << tab << "(";
for (Idx i = 0; i < conds.nbrDim(); i++) {
if (conds.val(i) != 0) break;
str << "(";
}
// condVars << *( varsSeq[(Idx)0] );
str << ") {" << std::endl << tab << "data = ";
inst.setVals(conds);
for (inst.setFirstVar(*varsSeq[0]); !inst.end(); inst.incVar(*varsSeq[0]))
str << tab << cpt[inst];
for (condVars.setFirst(); !condVars.end(); ++condVars) {
comment = tab + "% ";
for (Idx i = 0; i < conds.nbrDim(); i++) {
comment += conds.variable(i).name() + "=" +
conds.variable(i).label(conds.val(i)) + tab;
}
// Writing the probabilities of the variable
if (condVars.valFromPtr(varsSeq[(Idx)0]) !=
(varsSeq[(Idx)0])->domainSize() - 1 &&
condVars.valFromPtr(varsSeq[(Idx)0]) != 0) {
str << tab << cpt[condVars];
} else {
bool notend = false;
for (Idx i = 0; i < condVars.nbrDim(); i++) {
if (condVars.val(condVars.variable(i)) == 0) {
notend = true;
str << (i == 0 ? "\n " : "") << "(";
} else
break;
++conds;
if (conds.end()) {
for (Idx i = 0; i < inst.nbrDim(); i++) {
str << ")";
}
str << tab << cpt[condVars];
if (!notend) {
for (Idx i = 0; i < condVars.nbrDim(); i++) {
if (condVars.val(condVars.variable(i)) ==
condVars.variable(i).domainSize() - 1)
str << ")" << (i == condVars.nbrDim() - 1 ? ";" : "");
else
break;
}
str << ";" << comment;
break;
} else {
for (Idx i = 0; i < conds.nbrDim(); i++) {
str << ")";
if (conds.val(i) != 0) break;
}
str << comment << "\n" ;
}
}
// inst.unsetOverflow();
str << "\n}" << std::endl;
}
str << "\n}\n" << std::endl;
return str.str();
}
......@@ -183,8 +179,7 @@ namespace gum {
str << std::endl << "net {" << std::endl;
str << " name = " << bn.propertyWithDefault("name", "unnamedBN") << ";"
<< std::endl;
str << " software = \"aGrUM "
<< "\";" << std::endl;
str << " software = \"aGrUM " << GUM_VERSION << "\";" << std::endl;
str << " node_size = (50 50);" << std::endl;
str << "}" << std::endl;
return str.str();
......
......@@ -151,7 +151,7 @@ namespace gum {
* @param card The cardinality of the variable
* @return The \c NodeId of the variable in the network
*/
NodeId addNode(const std::string& name, const Size& card);
NodeId addVariable(const std::string& name, const Size& card);
/**
* @brief Adds an arc between two nodes.
......
......@@ -37,8 +37,8 @@ namespace gum {
}
template < typename GUM_SCALAR >
NodeId CredalNet< GUM_SCALAR >::addNode(const std::string& name,
const Size& card) {
NodeId CredalNet< GUM_SCALAR >::addVariable(const std::string& name,
const Size& card) {
LabelizedVariable var(name, "node " + name, card);
NodeId a = __src_bn.add(var);
......@@ -46,11 +46,11 @@ namespace gum {
NodeId c = __src_bn_max.add(var);
if (a != b || a != c /*|| b != c*/)
GUM_ERROR(
OperationNotAllowed,
"addNodeWithId : not the same id over all networks : " << a << ", " << b
<< ", "
<< c);
GUM_ERROR(OperationNotAllowed,
"addVariable : not the same id over all networks : " << a << ", "
<< b
<< ", "
<< c);
return a;
}
......
......@@ -790,7 +790,6 @@ namespace gum {
*/
Size operator()(const Debug& key) const;
};
} /* namespace gum */
/// include the inlined functions if necessary
......
......@@ -109,7 +109,6 @@ namespace gum {
/// returns a hashed key for hash tables the keys of which are represented
/// by vectors of Idx
INLINE Size HashFunc< std::vector< Idx > >::
operator()(const std::vector< Idx >& key) const {
Size h = 0;
......
......@@ -1038,6 +1038,11 @@ namespace gum {
// =========================================================================
/// @{
/**
* @brief operator==
*/
bool operator==(const Instantiation& other) const;
/**
* @brief Alias of Instantiation::inc().
* @return Returns this Instantiation.
......@@ -1230,6 +1235,20 @@ namespace gum {
*/
std::ostream& operator<<(std::ostream&, const Instantiation&);
/**
* @brief Hash function for gum::Instantiation.
* @ingroup hashfunctions_group
*/
template <>
class HashFunc< Instantiation > : public HashFuncBase< Instantiation > {
public:
/**
* @brief Computes the hashed value of a key.
* @param key The key to compute the hashed value.
* @return Returns the hashed value of a key.
*/
Size operator()(const Instantiation& key) const;
};
} /* namespace gum */
#ifndef GUM_NO_INLINE
......
......@@ -821,4 +821,25 @@ namespace gum {
__vars.setAtPos(__vars.pos(x), y);
}
/// returns a hashed key for hash tables the keys of which are represented
/// by vectors of Idx
INLINE Size HashFunc< Instantiation >::
operator()(const Instantiation& key) const {
Size h = 0;
for (const auto& k :
key.variablesSequence()) // k are unique only by address (not by name)
h += Size(k) * key.val(*k);
return ((h * HashFuncConst::gold) & this->_hash_mask);
}
INLINE bool Instantiation::operator==(const Instantiation& other) const {
if (inOverflow() && other.inOverflow()) return true;
if (other.nbrDim() != nbrDim()) return false;
for (const auto& k : variablesSequence()) {
if (!other.contains(k)) return false;
if (val(*k) != other.val(*k)) return false;
}
return true;
}
} /* namespace gum */
......@@ -203,6 +203,13 @@ namespace gum {
/// @throw NotFound if all value == 0.0
GUM_SCALAR minNonZero() const;
/// set of instantiation corresponding to the parameter v in the Potential
Set< Instantiation > findAll(GUM_SCALAR v) const;
/// set of instantiation corresponding to the max in the Potential
Set< Instantiation > argmax() const;
/// set of instantiation corresponding to the min in the Potential
Set< Instantiation > argmin() const;
/// entropy of the Potential
GUM_SCALAR entropy() const;
......
......@@ -587,4 +587,29 @@ namespace gum {
return out;
}
// argmax of all elements in this
template < typename GUM_SCALAR >
Set< Instantiation > Potential< GUM_SCALAR >::findAll(GUM_SCALAR v) const {
Instantiation I(*this);
Set< Instantiation > res;
if (static_cast< MultiDimContainer< GUM_SCALAR >* >(this->_content)->empty()) {
return res;
}
for (I.setFirst(); !I.end(); ++I) {
if (this->get(I) == v) res.insert(I);
}
return res;
}
// argmax of all elements in this
template < typename GUM_SCALAR >
INLINE Set< Instantiation > Potential< GUM_SCALAR >::argmax() const {
return findAll(max());
}
// argmin of all elements in this
template < typename GUM_SCALAR >
INLINE Set< Instantiation > Potential< GUM_SCALAR >::argmin() const {
return findAll(min());
}
} /* namespace gum */
......@@ -271,7 +271,7 @@ namespace gum_tests {
TS_ASSERT_EQUALS(v[i], i)
for (int i = 0; i < 5; i++)
nodeset.eraseNode(gum::randomValue(100));
nodeset.eraseNode(2 + i * 19);
nodeset.addNodes(5);
......
......@@ -1022,5 +1022,38 @@ namespace gum_tests {
TS_GUM_ASSERT_THROWS_NOTHING(pp.fillWith(p, {"w", "v"}));
TS_ASSERT_THROWS(pp.fillWith(p, {"v", "w"}), gum::InvalidArgument);
}
private:
void __testval_for_set(const gum::Potential< int >& p,
int val,
const gum::Set< gum::Instantiation > s,
gum::Size expected_size) {
gum::Instantiation ip(p);
TS_ASSERT_EQUALS(s.size(), expected_size);
for (ip.setFirst(); !ip.end(); ++ip) {
if (s.contains(ip)) {
TS_ASSERT_EQUALS(p[ip], val);
} else {
TS_ASSERT_DIFFERS(p[ip], val);
}
}
}
public:
void testArgMaxMinFindAll() {
gum::LabelizedVariable v("v", "v", 2), w("w", "w", 3);
gum::Potential< int > p;
__testval_for_set(p, 4, p.findAll(4), 0);
p.add(v);
p.add(w);
p.fillWith({1, 3, 2, 4, 1, 4});
__testval_for_set(p, 3, p.findAll(3), 1);
__testval_for_set(p, 10, p.findAll(10), 0);
__testval_for_set(p, 4, p.argmax(), 2);
__testval_for_set(p, 1, p.argmin(), 2);
}
};
}
......@@ -199,7 +199,7 @@ namespace gum_tests {
void testRead_file3() {
std::string file = GET_RESSOURCES_PATH("BIFReader_file3.bif");
gum::BayesNet< float >* net = new gum::BayesNet< float >();
auto net = new gum::BayesNet< float >();
gum::BIFReader< float > reader(net, file);
int nbrErr = 0;
......@@ -209,9 +209,9 @@ namespace gum_tests {
TS_ASSERT_EQUALS(reader.warnings(), (gum::Size)3);
// 3 warnings
TS_ASSERT_EQUALS(reader.errors(), (gum::Size)0);
TS_ASSERT(net != 0);
TS_ASSERT(net != nullptr);
if (net != 0) {
if (net != nullptr) {
gum::HashTable< std::string, gum::NodeId > idMap;
for (const auto node : net->nodes())
......
......@@ -326,6 +326,27 @@ namespace gum_tests {
}
}
void testOperatorEqual() {
gum::LabelizedVariable a("a", "first var", 2), b("b", "second var", 4),
c("c", "third var", 5), d("d", "fourth var", 2);
gum::MultiDimArray< char > p;
p << a << b << c;
gum::Instantiation i1(p), i2(p);
i2.setFirst();
++i2; // for i2 to be !=i1 in the first iteration
for (i1.setFirst(); !i1.end(); ++i1) {
TS_ASSERT_DIFFERS(i1, i2);
p.fromOffset(i2, p.toOffset(i1));
TS_ASSERT_EQUALS(i1, i2);
}
gum::Instantiation j;
TS_ASSERT_DIFFERS(i1, j);
j.inc(); // j is in overflow
TS_ASSERT_EQUALS(i1, j); // both are in overflow => equals
}
private:
// Builds a BN to test the inference
void fill(gum::BayesNet< double >& bn) {
......
......@@ -109,9 +109,9 @@ namespace gum_tests {
initCNet();
std::vector< gum::NodeId > ids;
ids.push_back(cn->addNode("A", 3)); // id 0
ids.push_back(cn->addNode("B", 3)); // id 1
ids.push_back(cn->addNode("C", 3)); // id 2
ids.push_back(cn->addVariable("A", 3)); // id 0
ids.push_back(cn->addVariable("B", 3)); // id 1
ids.push_back(cn->addVariable("C", 3)); // id 2
TS_ASSERT_EQUALS(ids[0], 0U);
TS_ASSERT_EQUALS(ids[1], 1U);
......
......@@ -9,3 +9,4 @@ For Windows
How to document
===============
http://www.sphinx-doc.org/en/stable/ext/example_numpy.html#example-numpy
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
......@@ -43,7 +43,7 @@ id : int
Returns
------
-------
int
the nodeId of the other node
"
......@@ -52,7 +52,7 @@ int
%feature("docstring") gum::Arc::first
"
Returns
------
-------
int
the nodeId of the first node of the arc (the tail)
"
......@@ -61,7 +61,7 @@ int
%feature("docstring") gum::Arc::second
"
Returns
------
-------
int
the nodeId of the second node of the arc (the head)
"
......@@ -25,11 +25,10 @@ Returns
pyAgrum.BayesNet
the generated Bayesian network
Warnings
--------
OperationNotAllowed raised if n_modmax < 2
Warnings
--------
OperationNotAllowed raised if n_arcs is incompatible with n_nodes (not enough arcs)
Raises
------
gum.OperationNotAllowed
If n_modmax < 2
gum.OperationNotAllowed
If n_arcs is incompatible with n_nodes (not enough arcs)
"
\ No newline at end of file
......@@ -52,13 +52,12 @@ Returns
pyAgrum.BayesNet
the learned BayesNet
Warnings
--------
MissingVariableInDatabase if a variable of the BN is not found in the database
Warnings
--------
UnknownLabelInDatabase raise if a label is found in the database that do not correspond to the variable
Raises
------
gum.MissingVariableInDatabase
If a variable of the BN is not found in the database
gum.UnknownLabelInDatabase
If a label is found in the database that do not correspond to the variable
"
%feature("docstring") gum::learning::BNLearner::setInitialDAG
......
......@@ -7,70 +7,6 @@ Available constructors:
``BayesNet(source) -> BayesNet``
Listeners could be added in order to monitor its loading.
Examples
--------
>>> import pyAgrum as gum
>>>
>>> # creating a new liseners
>>> def foo(progress):
>>> if progress==200:
>>> print(' BN loaded ')
>>> return
>>> elif progress==100:
>>> car='%'
>>> elif progress%10==0:
>>> car='#'
>>> else:
>>> car='.'
>>> print(car,end='',flush=True)
>>>
>>> def bar(progress):
>>> if progress==50:
>>> print('50%')
>>>
>>>
>>> gum.loadBN('./bn.bif',listeners=[foo,bar])
>>> # .........#.........#.........#.........#..50%
>>> # .......#.........#.........#.........#.........#.........% | bn loaded
Listeners could also be added when structural modification are made