45#ifndef DOXYGEN_SHOULD_SKIP_THIS
51# include <agrum/base/external/json/json.hpp>
52using json = nlohmann::json;
55 template < GUM_Numeric GUM_SCALAR >
57 std::string_view filename,
58 bool binary) :
BNReader< GUM_SCALAR >(bn, filename) {
59 GUM_CONSTRUCTOR(GumBNReader)
61 _streamName_ = filename;
66 template < GUM_Numeric GUM_SCALAR >
67 GumBNReader< GUM_SCALAR >::GumBNReader(BayesNet< GUM_SCALAR >* bn) :
68 BNReader< GUM_SCALAR >(bn,
"") {
69 GUM_CONSTRUCTOR(GumBNReader)
76 template < GUM_Numeric GUM_SCALAR >
77 GumBNReader< GUM_SCALAR >::~GumBNReader() {
78 GUM_DESTRUCTOR(GumBNReader)
81 template < GUM_Numeric GUM_SCALAR >
82 template <
typename JsonType >
83 Size GumBNReader< GUM_SCALAR >::_proceedFromJson_(
const JsonType& content) {
86 if (content.contains(
"type") && content[
"type"].template get< std::string >() !=
"BN") {
87 addError(
"Invalid GUM file format: expected 'BN' type, got '"
88 + content[
"type"].
template get< std::string >() +
"'",
95 if (!content.contains(
"nodes") || !content.contains(
"parents") || !content.contains(
"cpt")) {
96 addError(
"Invalid GUM file format: missing 'nodes', 'parents' or 'cpt' sections",
104 BayesNet< GUM_SCALAR > tmp;
106 for (
const auto& node: content[
"nodes"]) {
107 tmp.add(node.template get< std::string >());
110 for (
const auto& parent: content[
"parents"].items()) {
111 const auto& nodeName = parent.key();
112 for (
const auto& p: parent.value()) {
113 tmp.addArc(p.template get< std::string >(), nodeName);
117 for (
const auto& cpt: content[
"cpt"].items()) {
118 const auto& nodeName = cpt.key();
119 const auto& values = cpt.value();
120 tmp.cpt(nodeName).fillWith(values.template get< std::vector< double > >());
123 if (content.contains(
"properties")) {
124 for (
const auto& prop: content[
"properties"].items()) {
125 tmp.setProperty(prop.key(), prop.value().template get< std::string >());
128 *_bn_ = std::move(tmp);
137 template < GUM_Numeric GUM_SCALAR >
138 Size GumBNReader< GUM_SCALAR >::proceed() {
139 if (_parseDone_) {
return 0; }
140 if (_streamName_.empty()) {
142 "GumBNReader was constructed without a filename: use proceedFromString() instead "
147 std::ifstream file(_streamName_, _binary_ ? std::ios::binary : std::ios::in);
148 if (!file.is_open()) {
149 addException(
"No such file " + _streamName_, _streamName_);
154 = _binary_ ? json::from_msgpack(
_readVector_(file)) : json::parse(file, nullptr, false);
156 if (content.is_discarded()) {
157 addException(
"Error parsing file", _streamName_);
160 return _proceedFromJson_(content);
161 }
catch (
const std::exception& e) {
162 addException(std::string(
"Error reading binary file: ") + e.what(), _streamName_);
167 template < GUM_Numeric GUM_SCALAR >
168 Size GumBNReader< GUM_SCALAR >::proceedFromString(std::string_view content) {
169 if (_parseDone_) {
return 0; }
170 const auto j = json::parse(content,
nullptr,
false);
171 if (j.is_discarded()) {
172 addException(
"Invalid JSON string", _streamName_);
175 return _proceedFromJson_(j);
178 template < GUM_Numeric GUM_SCALAR >
179 void GumBNReader< GUM_SCALAR >::showElegantErrorsAndWarnings(std::ostream& stream)
const {
180 if (_parseDone_ || count() > 0) elegantErrorsAndWarnings(stream);
184 template < GUM_Numeric GUM_SCALAR >
185 void GumBNReader< GUM_SCALAR >::showErrorCounts(std::ostream& stream)
const {
186 if (_parseDone_ || count() > 0) syntheticResults(stream);
Shared binary I/O helpers for GUM (jgum/bgum) serialization.
Pure virtual class for reading a BN from a file.
Class representing a Bayesian network.
Base class for all aGrUM's exceptions.
GUM_NODISCARD std::string errorContent() const
Returns the message content.
GumBNReader(BayesNet< GUM_SCALAR > *bn, std::string_view filename, bool binary=false)
Constructor A reader is defined for reading a defined file.
Exception : operation not allowed.
#define GUM_ERROR(type, msg)
gum is the global namespace for all aGrUM entities
std::vector< uint8_t > _readVector_(std::istream &is)
Reads a length-prefixed byte vector from a binary stream (bgum format).