75 template < GUM_Numeric GUM_SCALAR >
77 std::string_view node,
78 std::string_view default_domain) {
82 if (mn.exists(v->name())) res = mn.idFromName(v->name());
83 else res = mn.add(*v);
87 template < GUM_Numeric GUM_SCALAR >
88 MarkovRandomField< GUM_SCALAR >
89 MarkovRandomField< GUM_SCALAR >::fastPrototype(std::string_view dotlike, Size domainSize) {
90 return fastPrototype(dotlike,
"[" + std::to_string(domainSize) +
"]");
93 template < GUM_Numeric GUM_SCALAR >
94 MarkovRandomField< GUM_SCALAR >
95 MarkovRandomField< GUM_SCALAR >::fastPrototype(std::string_view dotlike,
96 std::string_view domain) {
97 MarkovRandomField< GUM_SCALAR > mn;
102 for (
auto& node:
split(clikchain,
"--")) {
108 mn.generateFactors();
109 mn.setProperty(
"name",
"anonymousMRF");
113 template < GUM_Numeric GUM_SCALAR >
114 MarkovRandomField< GUM_SCALAR >
116 MarkovRandomField< GUM_SCALAR > mn;
117 for (
NodeId nod: bn.nodes()) {
118 mn.add(bn.variable(nod), nod);
120 mn.beginTopologyTransformation();
121 for (
NodeId nod: bn.nodes()) {
122 mn.addFactor(bn.cpt(nod));
124 mn.endTopologyTransformation();
125 mn.setProperty(
"name", bn.propertyWithDefault(
"name",
"noname"));
129 template < GUM_Numeric GUM_SCALAR >
130 MarkovRandomField< GUM_SCALAR >::MarkovRandomField() :
132 GUM_CONSTRUCTOR(MarkovRandomField);
135 template < GUM_Numeric GUM_SCALAR >
136 MarkovRandomField< GUM_SCALAR >::MarkovRandomField(std::string_view name) :
137 IMarkovRandomField< GUM_SCALAR >(name), _topologyTransformationInProgress_(false) {
138 GUM_CONSTRUCTOR(MarkovRandomField);
141 template < GUM_Numeric GUM_SCALAR >
142 MarkovRandomField< GUM_SCALAR >::MarkovRandomField(
143 const MarkovRandomField< GUM_SCALAR >& source) :
144 IMarkovRandomField< GUM_SCALAR >(source), _topologyTransformationInProgress_(false) {
145 GUM_CONS_CPY(MarkovRandomField);
146 _copyFactors_(source);
149 template < GUM_Numeric GUM_SCALAR >
150 MarkovRandomField< GUM_SCALAR >&
151 MarkovRandomField< GUM_SCALAR >::operator=(
const MarkovRandomField< GUM_SCALAR >& source) {
152 if (
this != &source) {
153 IMarkovRandomField< GUM_SCALAR >::operator=(source);
154 _topologyTransformationInProgress_ =
false;
155 _copyFactors_(source);
161 template < GUM_Numeric GUM_SCALAR >
162 MarkovRandomField< GUM_SCALAR >& MarkovRandomField< GUM_SCALAR >::operator=(
163 MarkovRandomField< GUM_SCALAR >&& source)
noexcept {
164 if (
this != &source) {
166 UGmodel::operator=(std::move(source));
167 _topologyTransformationInProgress_ =
false;
168 _factors_ = std::move(source._factors_);
169 source._rebuildGraph_();
170 GUM_OP_MOV(MarkovRandomField);
175 template < GUM_Numeric GUM_SCALAR >
176 MarkovRandomField< GUM_SCALAR >::~MarkovRandomField() {
178 GUM_DESTRUCTOR(MarkovRandomField);
181 template < GUM_Numeric GUM_SCALAR >
182 const DiscreteVariable& MarkovRandomField< GUM_SCALAR >::variable(std::string_view name)
const {
183 return variable(idFromName(name));
186 template < GUM_Numeric GUM_SCALAR >
187 void MarkovRandomField< GUM_SCALAR >::changeVariableName(NodeId
id, std::string_view new_name) {
188 this->varMap_.changeName(
id, new_name);
191 template < GUM_Numeric GUM_SCALAR >
192 void MarkovRandomField< GUM_SCALAR >::changeVariableName(std::string_view name,
193 std::string_view new_name) {
194 changeVariableName(idFromName(name), new_name);
197 template < GUM_Numeric GUM_SCALAR >
198 void MarkovRandomField< GUM_SCALAR >::changeVariableLabel(std::string_view name,
199 std::string_view old_label,
200 std::string_view new_label) {
201 changeVariableLabel(idFromName(name), old_label, new_label);
204 template < GUM_Numeric GUM_SCALAR >
205 void MarkovRandomField< GUM_SCALAR >::changeVariableLabel(NodeId
id,
206 std::string_view old_label,
207 std::string_view new_label) {
208 if (variable(
id).varType() != VarType::LABELIZED) {
211 auto* var =
dynamic_cast< LabelizedVariable*
>(
const_cast< DiscreteVariable*
>(&variable(
id)));
212 if (var ==
nullptr)
GUM_ERROR(
TypeError,
"Variable " <<
id <<
" is not a LabelizedVariable.")
214 var->changeLabel(var->posLabel(old_label), new_label);
217 template < GUM_Numeric GUM_SCALAR >
218 const Tensor< GUM_SCALAR >& MarkovRandomField< GUM_SCALAR >::factor(const NodeSet& varIds)
const {
219 return *_factors_[varIds];
222 template < GUM_Numeric GUM_SCALAR >
223 const NodeSet& MarkovRandomField< GUM_SCALAR >::smallestFactorFromNode(NodeId node)
const {
225 Size smallest = size() + 1;
226 for (
const auto& kv: factors()) {
227 const auto& fact = kv.first;
228 if (fact.contains(node))
229 if (smallest > fact.size()) {
231 smallest = fact.size();
234 if (res ==
nullptr) {
241 template < GUM_Numeric GUM_SCALAR >
242 const Tensor< GUM_SCALAR >&
243 MarkovRandomField< GUM_SCALAR >::factor(
const std::vector< std::string >& varnames)
const {
244 return factor(this->nodeset(varnames));
247 template < GUM_Numeric GUM_SCALAR >
248 const FactorTable< GUM_SCALAR >& MarkovRandomField< GUM_SCALAR >::factors()
const {
252 template < GUM_Numeric GUM_SCALAR >
253 NodeId MarkovRandomField< GUM_SCALAR >::add(std::string_view fast_description,
254 unsigned int default_nbrmod) {
255 auto v = fastVariable< GUM_SCALAR >(std::string{fast_description}, default_nbrmod);
260 template < GUM_Numeric GUM_SCALAR >
261 void MarkovRandomField< GUM_SCALAR >::_rebuildGraph_() {
262 if (_topologyTransformationInProgress_)
return;
264 this->graph_.clearEdges();
266 for (
const auto& kv: _factors_) {
267 auto& c = *kv.second;
268 for (Idx i = 0; i < c.nbrDim(); i++)
269 for (Idx j = i + 1; j < c.nbrDim(); j++)
270 this->graph_.addEdge(this->varMap_.get(c.variable(i)), this->varMap_.get(c.variable(j)));
274 template < GUM_Numeric GUM_SCALAR >
275 NodeId MarkovRandomField< GUM_SCALAR >::add(
const DiscreteVariable& var) {
279 template < GUM_Numeric GUM_SCALAR >
280 NodeId MarkovRandomField< GUM_SCALAR >::add(
const DiscreteVariable& var, NodeId
id) {
281 this->varMap_.insert(
id, var);
282 this->graph_.addNodeWithId(
id);
286 template < GUM_Numeric GUM_SCALAR >
287 void MarkovRandomField< GUM_SCALAR >::erase(
const DiscreteVariable& var) {
288 erase(this->varMap_.get(var));
291 template < GUM_Numeric GUM_SCALAR >
292 void MarkovRandomField< GUM_SCALAR >::erase(std::string_view name) {
293 erase(idFromName(name));
296 template < GUM_Numeric GUM_SCALAR >
297 void MarkovRandomField< GUM_SCALAR >::erase(NodeId varId) {
298 if (!this->varMap_.exists(varId)) {
301 this->varMap_.erase(varId);
302 this->graph_.eraseNode(varId);
304 std::vector< NodeSet > vs;
305 for (
const auto& kv: _factors_) {
306 if (kv.first.contains(varId)) { vs.push_back(kv.first); }
308 for (
const auto& ns: vs) {
311 for (
const auto& ns: vs) {
314 if (nv.size() > 1) addFactor(nv);
319 template < GUM_Numeric GUM_SCALAR >
320 void MarkovRandomField< GUM_SCALAR >::clear() {
321 if (!this->empty()) {
322 auto l = this->nodes();
323 for (
const auto no: l) {
330 template < GUM_Numeric GUM_SCALAR >
331 std::ostream&
operator<<(std::ostream& output,
const MarkovRandomField< GUM_SCALAR >& mn) {
332 output << mn.toString();
336 template < GUM_Numeric GUM_SCALAR >
337 Tensor< GUM_SCALAR >&
338 MarkovRandomField< GUM_SCALAR >::_addFactor_(
const std::vector< NodeId >& ordered_nodes) {
340 for (
auto node: ordered_nodes)
345 if (_factors_.exists(vars)) {
349 Tensor< GUM_SCALAR >* factor =
new Tensor< GUM_SCALAR >();
351 for (
auto node: ordered_nodes) {
352 factor->add(variable(node));
355 _factors_.insert(vars, factor);
361 template < GUM_Numeric GUM_SCALAR >
362 const Tensor< GUM_SCALAR >& MarkovRandomField< GUM_SCALAR >::addFactor(
const NodeSet& vars) {
364 std::vector< NodeId > sorted_nodes;
365 for (
auto node: vars) {
366 sorted_nodes.push_back(node);
368 std::sort(sorted_nodes.begin(), sorted_nodes.end());
370 return _addFactor_(sorted_nodes);
373 template < GUM_Numeric GUM_SCALAR >
374 const Tensor< GUM_SCALAR >&
375 MarkovRandomField< GUM_SCALAR >::addFactor(
const std::vector< std::string >& varnames) {
376 std::vector< NodeId > sorted_nodes;
377 for (
const auto& v: varnames) {
378 sorted_nodes.push_back(idFromName(v));
381 return _addFactor_(sorted_nodes);
384 template < GUM_Numeric GUM_SCALAR >
385 const Tensor< GUM_SCALAR >&
386 MarkovRandomField< GUM_SCALAR >::addFactor(
const Tensor< GUM_SCALAR >& factor) {
387 std::vector< NodeId > sorted_nodes;
388 for (Idx i = 0; i < factor.nbrDim(); i++) {
389 sorted_nodes.push_back(idFromName(factor.variable(i).name()));
391 auto& res = _addFactor_(sorted_nodes);
392 res.fillWith(factor);
397 template < GUM_Numeric GUM_SCALAR >
398 void MarkovRandomField< GUM_SCALAR >::generateFactors()
const {
399 for (
const auto& elt: _factors_) {
400 elt.second->random();
404 template < GUM_Numeric GUM_SCALAR >
405 void MarkovRandomField< GUM_SCALAR >::generateFactor(
const NodeSet& vars)
const {
406 _factors_[vars]->random();
409 template < GUM_Numeric GUM_SCALAR >
410 void MarkovRandomField< GUM_SCALAR >::eraseFactor(
const NodeSet& vars) {
411 if (_factors_.exists(vars)) {
419 template < GUM_Numeric GUM_SCALAR >
420 void MarkovRandomField< GUM_SCALAR >::eraseFactor(
const std::vector< std::string >& varnames) {
421 auto vars = this->nodeset(varnames);
422 if (_factors_.exists(vars)) {
430 template < GUM_Numeric GUM_SCALAR >
431 void MarkovRandomField< GUM_SCALAR >::_eraseFactor_(
const NodeSet& vars) {
432 delete _factors_[vars];
433 _factors_.erase(vars);
436 template < GUM_Numeric GUM_SCALAR >
437 void MarkovRandomField< GUM_SCALAR >::_clearFactors_() {
438 for (
const auto& kv: _factors_) {
445 template < GUM_Numeric GUM_SCALAR >
446 void MarkovRandomField< GUM_SCALAR >::_copyFactors_(
447 const MarkovRandomField< GUM_SCALAR >& source) {
449 for (
const auto& pf: source.factors()) {
450 addFactor(*pf.second);
455 template < GUM_Numeric GUM_SCALAR >
456 void MarkovRandomField< GUM_SCALAR >::beginTopologyTransformation() {
457 _topologyTransformationInProgress_ =
true;
460 template < GUM_Numeric GUM_SCALAR >
461 void MarkovRandomField< GUM_SCALAR >::endTopologyTransformation() {
462 if (_topologyTransformationInProgress_) {
463 _topologyTransformationInProgress_ =
false;
Class representing Markov random fields.
Class representing a Bayesian network.
Class representing the minimal interface for Markov random field.
Exception: at least one argument passed to a function is not what was expected.
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
void insert(const Key &k)
Inserts a new element into the set.
void erase(const Key &k)
Erases an element from the set.
Exception : wrong type for this operation.
#define GUM_ERROR(type, msg)
Size NodeId
Type for node ids.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
std::string remove_newline(std::string_view s)
remove all newlines in a string
std::vector< std::string > split(std::string_view str, std::string_view delim)
Split str using the delimiter.
class for LOGIT implementation as multiDim
class for NoisyAND-net implementation as multiDim
class for multiDimNoisyORCompound
class for NoisyOR-net implementation as multiDim
NodeId nextNodeId()
Returns the next value of an unique counter for PRM's node id.
gum is the global namespace for all aGrUM entities
NodeId build_node_for_MN(MarkovRandomField< GUM_SCALAR > &mn, std::string_view node, std::string_view default_domain)
std::unique_ptr< DiscreteVariable > fastVariable(std::string var_description, Size default_domain_size)
Create a pointer on a Discrete Variable from a "fast" syntax.
Abstract class for generating Conditional Probability Tables.
std::ostream & operator<<(std::ostream &out, const TiXmlNode &base)
Utilities for manipulating strings.