45#ifndef DOXYGEN_SHOULD_SKIP_THIS
55 template < GUM_Numeric GUM_SCALAR,
template <
class >
class IApproximationPolicy >
57 IApproximationPolicy >::ContextualDependenciesCNFWriter() {
62 template < GUM_Numeric GUM_SCALAR,
template <
class >
class IApproximationPolicy >
64 IApproximationPolicy >::~ContextualDependenciesCNFWriter() {
74 template < GUM_Numeric GUM_SCALAR,
template <
class >
class IApproximationPolicy >
80 for (
auto node: bn.topologicalOrder())
81 Order.
add(bn.variable(node));
83 if (!output.good())
GUM_ERROR(IOError,
"Input/Output error : stream not writable.")
85 std::stringstream strfile;
86 std::stringstream strfile2;
91 std::stringstream clausstr;
92 std::stringstream clausstr2;
100 for (auto node: bn.nodes()) {
101 std::stringstream str0;
104 for (
Idx i = 0; i < var->domainSize(); i++) {
105 auto stri = std::format(
"{}_{}", var->name(), var->label(i));
106 vartable.insert(stri, ++num);
107 strfile << std::format(
"{}::{}\n", num, stri);
108 str0 << std::format(
"{} ", vartable[stri]);
114 clausstr2 << str0.str();
121 new gum::HashTable< std::string,
122 gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >());
124 for (inst.setFirst(); !inst.end(); ++inst) {
125 if (this->fromExact(cpt[inst]) != 1) {
126 std::string valp = std::format(
"{}", this->fromExact(cpt[inst]));
128 if (!(cptparamval[var])->exists(valp)) {
130 ->insert(valp,
new gum::Sequence< gum::Sequence< gum::Instantiation* >* >());
132 (*(cptparamval[var]))[valp]->insert(
new gum::Sequence< gum::Instantiation* >);
134 if (this->fromExact(cpt[inst])) {
135 auto strinst = std::format(
"{}_val={}", var->name(), this->fromExact(cpt[inst]));
137 if (!protable.exists(strinst)) {
138 protable.insert(strinst, ++num);
139 strfile << std::format(
"{}::{}\n", num, strinst);
144 (*(cptparamval[var]))[valp]->front()->insert(
new gum::Instantiation(inst));
149 std::stringstream str2;
151 while (!cptparamval.empty()) {
152 auto itvar = cptparamval.begin();
154 while (!(itvar.val())->empty()) {
155 auto itpvall = (itvar.val())->begin();
157 for (
auto pv: *itpvall.val()) {
159 gum::HashTable< std::string,
160 gum::HashTable<
const gum::DiscreteVariable*,
161 std::pair< gum::Set< Idx >*,
162 gum::Set< Idx >* >* >* >
165 for (
const auto* seqv: *pv) {
166 if (seqv->nbrDim() > 1) {
167 for (
Idx iInst = 0; iInst < seqv->nbrDim(); iInst++) {
168 gum::Instantiation instpro(*seqv,
false);
169 instpro.reorder(Order);
170 const gum::DiscreteVariable* var = &(seqv->variable(iInst));
174 if (!orderStruct.exists(instpro.toString())) {
177 new gum::HashTable<
const gum::DiscreteVariable*,
178 std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >());
181 if (!orderStruct[instpro.toString()]->exists(var)) {
182 orderStruct[instpro.toString()]->insert(
184 new std::pair< gum::Set< Idx >*, gum::Set< Idx >* >(
187 seqv->variable(iInst).domainSize())));
190 gum::HashTable<
const gum::DiscreteVariable*,
191 std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >* orderStruct2
192 = orderStruct[instpro.toString()];
193 (*orderStruct2)[var]->first->insert(linecount);
194 (*orderStruct2)[var]->second->insert(seqv->val(iInst));
201 gum::Set< gum::Idx > elimination;
202 gum::Sequence< gum::Instantiation* >* newSeq =
nullptr;
204 for (
const auto& [first, second]: orderStruct) {
207 for (
const auto& [first2, second2]: *second) {
208 if (second2->second->size() == first2->domainSize()) {
209 if (!newSeq) newSeq =
new gum::Sequence< gum::Instantiation* >();
214 new gum::Instantiation(*((*pv)[(*(second2->first->begin()))]),
false));
215 newSeq->
back()->erase(*first2);
218 elimination = elimination + *(second2->first);
224 (itpvall.val())->insert(newSeq);
226 for (
Idx itelem = pv->size(); itelem > 0; itelem--) {
227 if (elimination.
exists(itelem - 1)) {
228 delete ((*pv)[itelem - 1]);
229 pv->erase((*pv)[itelem - 1]);
234 while (!orderStruct.empty()) {
235 while (!(orderStruct.begin().val())->empty()) {
236 delete orderStruct.begin().val()->begin().val()->first;
237 delete orderStruct.begin().val()->begin().val()->second;
238 (orderStruct.begin().val())
239 ->erase((orderStruct.begin().val())->beginSafe());
242 delete orderStruct.begin().val();
243 orderStruct.erase(orderStruct.beginSafe());
247 while (!(itpvall.val())->empty()) {
248 auto itpv = (itpvall.val())->begin();
250 while (!(*itpv)->empty()) {
251 auto itseqv = (*itpv)->begin();
253 for (
Idx i = 0; i < (*itseqv)->nbrDim(); i++) {
254 auto str = std::format(
"{}_{}",
255 (*itseqv)->variable(i).name(),
256 (*itseqv)->val((*itseqv)->variable(i)));
257 str2 << std::format(
"-{} ", vartable[str]);
260 if (itpvall.key() !=
"0" && itpvall.key() !=
"0.0") {
261 auto strinst = std::format(
"{}_val={}", itvar.key()->name(), itpvall.key());
262 str2 << protable[strinst];
268 (*itpv)->erase(itseqv);
272 (itpvall.val())->erase(itpv);
275 delete (itpvall.val());
276 (itvar.val())->erase(itvar.val()->beginSafe());
279 delete (itvar.val());
280 cptparamval.erase(cptparamval.beginSafe());
283 clausstr << str2.str();
285 output << std::format(
"p cnf {} {}\neclauses {}\n", num, clause, numvar) << clausstr.str()
286 << clausstr2.str() <<
'\n';
297 template < GUM_Numeric GUM_SCALAR,
template <
class >
class IApproximationPolicy >
299 std::string_view filePath,
301 std::ofstream output(std::filesystem::path{filePath}, std::ios_base::trunc);
302 std::ofstream outputvar(std::string{filePath} +
".var", std::ios_base::trunc);
304 if (!output.good())
GUM_ERROR(IOError,
"Input/Output error : " << filePath <<
" not writable.")
306 std::stringstream strfile, strfile2;
308 if (!outputvar.good())
310 "Input/Output error : " << (std::
string(filePath) +
".var") <<
" not writable.")
315 std::stringstream clausstr, clausstr2;
325 for (auto node: bn.topologicalOrder())
326 Order.add(bn.variable(node));
328 for (auto node: bn.nodes()) {
329 std::stringstream str0;
332 for (
Idx i = 0; i < bn.variable(node).domainSize(); i++) {
333 auto stri = std::format(
"{}_{}", var->name(), var->label(i));
334 vartable.insert(stri, ++num);
335 strfile << std::format(
"{}::{}\n", num, stri);
336 str0 << std::format(
"{} ", vartable[stri]);
342 clausstr2 << str0.str();
349 new gum::HashTable< std::string,
350 gum::Sequence< gum::Sequence< gum::Instantiation* >* >* >());
352 for (inst.setFirst(); !inst.end(); ++inst) {
353 if (this->fromExact(cpt[inst]) != 1) {
354 std::string valp = std::format(
"{}", this->fromExact(cpt[inst]));
356 if (!(cptparamval[var])->exists(valp)) {
360 new gum::Sequence< gum::Sequence< gum::Instantiation* >* >());
366 (*(cptparamval[var]))[valp]->insert(
new gum::Sequence< gum::Instantiation* >);
368 if (this->fromExact(cpt[inst])) {
369 auto strinst = std::format(
"{}_val={}", var->name(), this->fromExact(cpt[inst]));
371 if (!protable.exists(strinst)) {
372 protable.insert(strinst, ++num);
373 strfile << std::format(
"{}::{}\n", num, strinst);
378 (*(cptparamval[var]))[valp]->front()->insert(
new gum::Instantiation(inst));
383 std::stringstream str2;
385 while (!cptparamval.empty()) {
386 auto itvar = cptparamval.begin();
388 while (!(itvar.val())->empty()) {
389 auto itpvall = (itvar.val())->begin();
391 for (
auto pv: *itpvall.val()) {
393 gum::HashTable< std::string,
394 gum::HashTable<
const gum::DiscreteVariable*,
395 std::pair< gum::Set< Idx >*,
396 gum::Set< Idx >* >* >* >
399 gum::Set< gum::Idx > elimination;
400 gum::HashTable< std::string, gum::Instantiation* > newSeqpre;
402 for (
const auto* seqv: *pv) {
403 if (seqv->nbrDim() > 1) {
404 for (
Idx iInst = 0; iInst < seqv->nbrDim(); iInst++) {
405 auto instpro =
new gum::Instantiation(*seqv,
false);
406 const gum::DiscreteVariable* var = &(seqv->variable(iInst));
407 instpro->erase(*var);
408 instpro->reorder(Order);
410 if (!orderStruct.exists(instpro->toString())
411 && !newSeqpre.
exists(instpro->toString())) {
414 new gum::HashTable<
const gum::DiscreteVariable*,
415 std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >());
418 if (orderStruct.exists(instpro->toString())
419 && !orderStruct[instpro->toString()]->exists(var)) {
420 orderStruct[instpro->toString()]->insert(
422 new std::pair< gum::Set< Idx >*, gum::Set< Idx >* >(
425 seqv->variable(iInst).domainSize())));
428 if (orderStruct.exists(instpro->toString())
429 && !newSeqpre.
exists(instpro->toString())) {
430 gum::HashTable<
const gum::DiscreteVariable*,
431 std::pair< gum::Set< Idx >*, gum::Set< Idx >* >* >* orderStruct2
432 = orderStruct[instpro->toString()];
433 (*orderStruct2)[var]->first->insert(linecount);
434 (*orderStruct2)[var]->second->insert(seqv->val(iInst));
436 if ((*orderStruct2)[var]->second->size() == var->
domainSize()) {
437 newSeqpre.
insert(instpro->toString(), instpro);
439 for (
const auto& elt: *orderStruct2) {
440 elimination = elimination + *(elt.second->first);
441 delete (elt.second->first);
442 delete (elt.second->second);
446 orderStruct2->clear();
449 orderStruct.erase(instpro->toString());
450 }
else delete instpro;
451 }
else if (newSeqpre.
exists(instpro->toString())) {
452 elimination.
insert(linecount);
461 gum::Sequence< gum::Instantiation* >* newSeq =
nullptr;
463 if (!newSeqpre.
empty()) {
464 newSeq =
new gum::Sequence< gum::Instantiation* >();
466 for (
auto& elt: newSeqpre)
467 newSeq->
insert(elt.second);
469 (itpvall.val())->insert(newSeq);
471 for (
Idx itelem = pv->size(); itelem > 0; itelem--) {
472 if (elimination.
exists(itelem - 1)) {
473 delete ((*pv)[itelem - 1]);
474 pv->erase((*pv)[itelem - 1]);
479 while (!orderStruct.empty()) {
480 while (!(orderStruct.begin().val())->empty()) {
481 delete orderStruct.begin().val()->begin().val()->first;
482 delete orderStruct.begin().val()->begin().val()->second;
483 (orderStruct.begin().val())->erase(orderStruct.begin().val()->beginSafe());
488 delete orderStruct.begin().val();
489 orderStruct.erase(orderStruct.beginSafe());
493 while (!(itpvall.val())->empty()) {
494 gum::Sequence< gum::Sequence< gum::Instantiation* >* >::iterator_safe itpv
495 = (itpvall.val())->begin();
497 while (!(*itpv)->empty()) {
500 for (
Idx i = 0; i < (*itseqv)->nbrDim(); i++) {
501 auto str = std::format(
"{}_{}",
502 (*itseqv)->variable(i).name(),
503 (*itseqv)->val((*itseqv)->variable(i)));
504 str2 << std::format(
"-{} ", vartable[str]);
509 if (itpvall.key() !=
"0" && itpvall.key() !=
"0.0") {
510 auto strinst = std::format(
"{}_val={}", itvar.key()->name(), itpvall.key());
511 str2 << protable[strinst];
517 (*itpv)->erase((*itpv)->beginSafe());
521 (itpvall.val())->erase(itpvall.val()->beginSafe());
524 delete (itpvall.val());
525 (itvar.val())->erase(itvar.val()->beginSafe());
528 delete (itvar.val());
529 cptparamval.erase(cptparamval.beginSafe());
532 clausstr << str2.str();
534 output << std::format(
"p cnf {} {}\neclauses {}\n", num, clause, numvar) << clausstr.str()
535 << clausstr2.str() <<
'\n';
537 outputvar << strfile.str();
543 if (outputvar.fail())
GUM_ERROR(IOError,
"Writing in the ostream failed.")
545 if (output.fail())
GUM_ERROR(IOError,
"Writing in the ostream failed.")
Definition of classe for BN file output manipulation.
<agrum/BN/io/cnf/ContextualDependenciesCNFWriter.h>
void _doWrite(std::ostream &output, const IBayesNet< GUM_SCALAR > &bn) final
Writes a Bayesian network in the output stream using the BN format.
Base class for discrete random variable.
virtual Size domainSize() const =0
The class for generic Hash Tables.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
bool empty() const noexcept
Indicates whether the hash table is empty.
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
Class representing the minimal interface for Bayesian network with no numerical data.
Class for assigning/browsing values to tuples of discrete variables.
void add(const DiscreteVariable &v) final
Adds a new variable in the Instantiation.
void insert(const Key &k)
Insert an element at the end of the sequence.
const Key & back() const
Returns the last element of the sequence.
The generic class for storing (ordered) sequences of objects.
SequenceIteratorSafe< Key > iterator_safe
Types for STL compliance.
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
void insert(const Key &k)
Inserts a new element into the set.
aGrUM's Tensor is a multi-dimensional array with tensor operators.
#define GUM_ERROR(type, msg)
Size Idx
Type for indexes.
gum is the global namespace for all aGrUM entities