61 template < GUM_Numeric GUM_SCALAR >
64 std::string_view domain) {
68 std::string ds(domain);
69 switch (*(node.begin())) {
79 default : isChanc =
true;
84 if (infdiag.
exists(v->name())) {
92 "No type (chance, decision or utility) for the node '" << node <<
"'.")
98 template < GUM_Numeric GUM_SCALAR >
99 InfluenceDiagram< GUM_SCALAR >
101 return fastPrototype(dotlike,
"[" + std::to_string(domainSize) +
"]");
104 template < GUM_Numeric GUM_SCALAR >
107 std::string_view domain) {
111 = [&](
const std::string& node) {
return build_node_for_ID(infdiag, node, domain); };
113 auto addEdge = [&](
NodeId,
NodeId,
const std::string& token) {
115 "fastPrototype: '" << token <<
"' is preceded by '-' but an InfluenceDiagram "
116 <<
"does not support edges")
121 fastGraphWalkTokens(fastGraphTokenize(chaine), dotlike, resolve,
addArc, addEdge);
124 for (
const auto n: infdiag.
nodes()) {
140 template < GUM_Numeric GUM_SCALAR >
148 template < GUM_Numeric GUM_SCALAR >
154 template < GUM_Numeric GUM_SCALAR >
163 template < GUM_Numeric GUM_SCALAR >
166 if (
this != &source) {
180 template < GUM_Numeric GUM_SCALAR >
189 template < GUM_Numeric GUM_SCALAR >
192 if (
this != &source) {
201 template < GUM_Numeric GUM_SCALAR >
205 this->varMap_.clear();
208 _utilityMap_.clear();
214 template < GUM_Numeric GUM_SCALAR >
225 template < GUM_Numeric GUM_SCALAR >
228 for (
auto node: IDsource.
nodes()) {
235 for (
auto node: IDsource.
nodes()) {
239 addArc(IDsource.
cpt(node).variable(par).name(), s);
251 for (
auto node: IDsource.
nodes()) {
254 cpt(node).fillWith(IDsource.
cpt(s));
261 template < GUM_Numeric GUM_SCALAR >
263 std::stringstream output;
264 std::stringstream decisionNode;
265 std::stringstream utilityNode;
266 std::stringstream chanceNode;
267 std::stringstream arcstream;
269 output << std::format(
"digraph \"{}\" {{\n", this->
propertyWithDefault(
"name",
"no_name"));
271 output <<
" node [bgcolor=\"#AAAAAA\", style=filled, height=0];" << std::endl;
273 decisionNode <<
"node [shape = box];" << std::endl;
275 utilityNode <<
"node [shape = hexagon, margin=0];" << std::endl;
276 chanceNode <<
"node [shape = ellipse];" << std::endl;
277 std::string tab =
" ";
279 for (
const auto node:
dag_.nodes()) {
281 chanceNode << std::format(
" \"{}-{}\";", node,
variable(node).name());
283 utilityNode << std::format(
" \"{}-{}\";", node,
variable(node).name());
284 else decisionNode << std::format(
" \"{}-{}\";", node,
variable(node).name());
286 if (
dag_.children(node).size() > 0)
287 for (
const auto chi:
dag_.children(node)) {
288 arcstream << std::format(
"\"{}-{}\" -> \"{}-{}\"",
293 if (
isDecisionNode(chi)) { arcstream <<
" [style=\"tapered, bold\"]"; }
298 output << decisionNode.str() << std::endl
299 << utilityNode.str() << std::endl
300 << chanceNode.str() << std::endl
302 << arcstream.str() << std::endl
308 template < GUM_Numeric GUM_SCALAR >
310 std::stringstream output;
312 output <<
"Influence Diagram{" << std::endl;
316 output << std::format(
" arcs: {},\n",
dag().
sizeArcs());
319 output << std::format(
" domainSize: 10^{}", dSize);
320 else output << std::format(
" domainSize: {}", std::round(std::pow(10.0, dSize)));
322 output << std::endl <<
"}";
334 template < GUM_Numeric GUM_SCALAR >
342 template < GUM_Numeric GUM_SCALAR >
350 template < GUM_Numeric GUM_SCALAR >
358 template < GUM_Numeric GUM_SCALAR >
370 template < GUM_Numeric GUM_SCALAR >
378 template < GUM_Numeric GUM_SCALAR >
386 template < GUM_Numeric GUM_SCALAR >
394 template < GUM_Numeric GUM_SCALAR >
403 template < GUM_Numeric GUM_SCALAR >
413 template < GUM_Numeric GUM_SCALAR >
421 if (newMultiDim !=
nullptr)
delete newMultiDim;
432 template < GUM_Numeric GUM_SCALAR >
442 template < GUM_Numeric GUM_SCALAR >
461 template < GUM_Numeric GUM_SCALAR >
468 auto varcpt =
new Tensor< GUM_SCALAR >(aContent);
480 template < GUM_Numeric GUM_SCALAR >
487 "Utility var have no state ( which implicates a "
488 "single label for data output reasons ).")
493 auto varut =
new Tensor< GUM_SCALAR >(aContent);
505 template < GUM_Numeric GUM_SCALAR >
511 if (DesiredId == 0) proposedId =
dag_.nextNodeId();
512 else proposedId = DesiredId;
514 this->
varMap_.insert(proposedId, variableType);
516 dag_.addNodeWithId(proposedId);
527 template < GUM_Numeric GUM_SCALAR >
529 if (this->
varMap_.exists(varId)) {
531 for (
const auto chi:
dag_.children(varId))
544 dag_.eraseNode(varId);
553 template < GUM_Numeric GUM_SCALAR >
560 template < GUM_Numeric GUM_SCALAR >
562 this->
varMap_.changeName(
id, new_name);
571 template < GUM_Numeric GUM_SCALAR >
575 dag_.addArc(tail, head);
591 template < GUM_Numeric GUM_SCALAR >
593 if (
dag_.existsArc(arc)) {
612 template < GUM_Numeric GUM_SCALAR >
624 template < GUM_Numeric GUM_SCALAR >
626 for (
const auto node:
dag_.nodes())
629 for (
const auto node:
dag_.nodes()) {
631 for (
const auto par:
dag_.parents(node)) {
634 for (
const auto par2:
dag_.parents(node))
635 if (par != par2)
graph.addEdge(par, par2);
643 template < GUM_Numeric GUM_SCALAR >
653 if (orderIter == order.
end())
return true;
655 NodeId parentDecision = (*orderIter);
659 while (orderIter != order.
end()) {
663 parentDecision = *orderIter;
675 template < GUM_Numeric GUM_SCALAR >
683 mark[src] = (int)src;
686 while (!nodeFIFO.
empty()) {
687 current = nodeFIFO.
front();
690 for (
const auto new_one:
dag_.children(current)) {
691 if (mark[new_one] != -1)
continue;
693 mark[new_one] = (int)current;
695 if (new_one == dest)
break;
701 if (mark[dest] == -1)
return false;
709 template < GUM_Numeric GUM_SCALAR >
713 for (
const auto node:
dag_.nodes()) {
720 temporalGraph.
addArc(node, chi);
725 return temporalGraph;
731 template < GUM_Numeric GUM_SCALAR >
743 mark[parentDecision] =
true;
747 while (!nodeFIFO.
empty()) {
748 current = nodeFIFO.
front();
751 for (
const auto new_one:
dag_.children(current)) {
752 if (mark[new_one])
continue;
754 mark[new_one] =
true;
757 else childrenSeq.
insert(new_one);
768 template < GUM_Numeric GUM_SCALAR >
772 std::vector< NodeId > decisionSequence;
777 return decisionSequence;
784 template < GUM_Numeric GUM_SCALAR >
792 for (
auto i: order) {
795 for (
const auto par:
dag_.parents(i)) {
797 partialOrderedSet.
insert(par);
813 for (
const auto node: nodeList)
822 template < GUM_Numeric GUM_SCALAR >
824 unsigned int default_nbrmod) {
830 template < GUM_Numeric GUM_SCALAR >
833 if (v->domainSize() >= 2)
835 v->name() <<
" has a domain size >= 2 which is impossible for a utility node")
839 template < GUM_Numeric GUM_SCALAR >
841 unsigned int default_nbrmod) {
847 template < GUM_Numeric GUM_SCALAR >
849 unsigned int default_nbrmod) {
850 std::string node(fast_description);
851 switch (*(node.begin())) {
852 case '*' : node.erase(0, 1);
return addDecisionNode(node, default_nbrmod);
854 default :
return addChanceNode(fast_description, default_nbrmod);
859 template < GUM_Numeric GUM_SCALAR >
861 for (
const auto node:
nodes())
867 template < GUM_Numeric GUM_SCALAR >
869 for (
const auto node:
nodes())
874 template < GUM_Numeric GUM_SCALAR >
876 if (
size() != from.
size()) {
return false; }
883 for (
auto node:
nodes()) {
885 if (!from.
exists(v1.name()))
return false;
887 if (v1 != v2) {
return false; }
898 if (p1.
nbrDim() != p2.nbrDim()) {
return false; }
900 if (p1.
domainSize() != p2.domainSize()) {
return false; }
906 for (
Idx indice = 0; indice < p1.
nbrDim(); ++indice) {
911 if (std::pow(p1.
get(i) - p2.get(j), (GUM_SCALAR)2) > (GUM_SCALAR)1e-6) {
return false; }
915 for (
auto node:
nodes()) {
918 if (!check_pot(
cpt(node), from.
cpt(fromnode))) {
return false; }
920 if (!check_pot(
utility(node), from.
utility(fromnode))) {
return false; }
927 template < GUM_Numeric GUM_SCALAR >
932 template < GUM_Numeric GUM_SCALAR >
937 template < GUM_Numeric GUM_SCALAR >
942 template < GUM_Numeric GUM_SCALAR >
947 template < GUM_Numeric GUM_SCALAR >
952 template < GUM_Numeric GUM_SCALAR >
957 template < GUM_Numeric GUM_SCALAR >
962 template < GUM_Numeric GUM_SCALAR >
964 std::string_view new_name) {
968 template < GUM_Numeric GUM_SCALAR >
973 template < GUM_Numeric GUM_SCALAR >
978 template < GUM_Numeric GUM_SCALAR >
980 std::string_view dest)
const {
The base class for all directed edges.
GUM_NODISCARD NodeId head() const
returns the head of the arc
GUM_NODISCARD NodeId tail() const
returns the tail of the arc
const T2 & second(const T1 &first) const
Returns the second value of a pair given its first value.
void insert(const T1 &first, const T2 &second)
Inserts a new association in the gum::Bijection.
Set of pairs of elements with fast search for both elements.
void addArc(NodeId tail, NodeId head) final
insert a new arc into the directed graph
DAG dag_
The DAG of this Directed Graphical Model.
DAGmodel()
Default constructor.
Size size() const final
Returns the number of variables in this Directed Graphical Model.
Size sizeArcs() const
Returns the number of arcs in this Directed Graphical Model.
Sequence< NodeId > topologicalOrder() const
The topological order stays the same as long as no variable or arcs are added or erased src the topol...
DAG dag() const
Returns a named copy of the internal DAG: each node id is assigned the name of the corresponding vari...
DAGmodel & operator=(const DAGmodel &source)
Private copy operator.
bool exists(NodeId node) const final
Return true if this node exists in this graphical model.
const NodeSet & parents(const NodeId id) const
returns the set of nodes with arc ingoing to a given node
const NodeGraphPart & nodes() const final
Returns a named copy of the internal DAG: each node id is assigned the name of the corresponding vari...
VariableNodeMap varMap_
Mapping between NodeIds and discrete variables.
Base class for discrete random variable.
virtual Size domainSize() const =0
Base class for all aGrUM's exceptions.
Exception : fatal (unknown ?) error.
void setProperty(std::string_view name, std::string_view value)
Add or change a property of this GraphicalModel.
double log10DomainSize() const
const std::string & propertyWithDefault(std::string_view name, const std::string &byDefault) const
Return the value of the property name of this GraphicalModel.
Class representing an Influence Diagram.
void beginTopologyTransformation()
When inserting/removing arcs, node CPTs/utilities change their dimension with a cost in time.
List< NodeSet > _temporalOrder_
The temporal order.
NodeId idFromName(std::string_view name) const override
Returns the NodeId of a variable given its name.
Size chanceNodeSize() const
Returns the number of chance nodes.
InfluenceDiagram()
Default constructor.
const List< NodeSet > & getPartialTemporalOrder(bool clear=true) const
Returns partial temporal ordering.
NodeId addChanceNode(const DiscreteVariable &variable, NodeId id=0)
Add a chance variable, it's associate node and it's CPT.
void addArc(NodeId tail, NodeId head)
Add an arc in the ID, and update diagram's tensor nodes cpt if necessary.
void endTopologyTransformation()
terminates a sequence of insertions/deletions of arcs by adjusting all CPTs/utilities dimensions.
static InfluenceDiagram< GUM_SCALAR > fastPrototype(std::string_view dotlike, Size domainSize)
Create an Influence Diagram with a dot-like syntax which specifies:
void removeTables_()
Removing ancient table.
void eraseArc(const Arc &arc)
Removes an arc in the ID, and update diagram's tensor nodes cpt if necessary.
NodeProperty< Tensor< GUM_SCALAR > * > _tensorMap_
Mapping between tensor variable's id and their CPT.
virtual void moralGraph_(UndiGraph &graph) const
Returns the moral graph of this InfluenceDiagram.
NodeId addNode_(const DiscreteVariable &variableType, NodeId DesiredId)
Add a node.
std::string toDot() const
bool decisionOrderExists() const
True if a directed path exist with all decision nodes.
bool isChanceNode(NodeId varId) const
Returns true if node is a chance one.
InfluenceDiagram< GUM_SCALAR > & operator=(const InfluenceDiagram< GUM_SCALAR > &source)
Copy Operator.
NodeId add(const DiscreteVariable &variable, NodeId id=0)
Add a chance variable, it's associate node and it's CPT.
NodeId addUtilityNode(const DiscreteVariable &variable, NodeId id=0)
Add a utility variable, it's associate node and it's UT.
std::string toString() const
void copyStructureAndTables_(const InfluenceDiagram< GUM_SCALAR > &IDsource)
Copying tables from another influence diagram.
NodeId addDecisionNode(const DiscreteVariable &variable, NodeId id=0)
Add a decision variable.
const DiscreteVariable & variableFromName(std::string_view name) const override
Returns a constant reference over a variable given its name.
bool isUtilityNode(NodeId varId) const
Returns true if node is a utility one.
bool operator==(const InfluenceDiagram< GUM_SCALAR > &other) const
Size utilityNodeSize() const
Returns the number of utility nodes.
NodeProperty< Tensor< GUM_SCALAR > * > _utilityMap_
Mapping between utility variable's id and their utility table.
gum::DAG getDecisionGraph() const
Returns the temporal Graph.
void changeVariableName(NodeId id, std::string_view new_name)
we allow the user to change the name of a variable
bool isDecisionNode(NodeId varId) const
Returns true if node is a decision one.
const DiscreteVariable & variable(std::string_view name) const
Returns the CPT of a tensor variable.
Sequence< NodeId > getChildrenDecision_(NodeId parentDecision) const
Returns the list of children decision for a given nodeId.
Size decisionNodeSize() const
Returns the number of decision nodes.
void erase(NodeId id)
Erase a Variable from the network and remove the variable from all his children.
virtual const Tensor< GUM_SCALAR > & cpt(NodeId varId) const
Returns the CPT of a tensor variable.
std::vector< NodeId > decisionOrder() const
Returns the sequence of decision nodes in the directed path.
virtual const Tensor< GUM_SCALAR > & utility(NodeId varId) const
Returns the utility table of a utility node.
bool existsPathBetween(NodeId src, NodeId dest) const
Returns true if a path exists between two nodes.
~InfluenceDiagram() override
Destructor.
Class for assigning/browsing values to tuples of discrete variables.
Instantiation & chgVal(const DiscreteVariable &v, Idx newval)
Assign newval to variable v in the Instantiation.
bool end() const
Returns true if the Instantiation reached the end.
void inc()
Operator increment.
Idx val(Idx i) const
Returns the current value of the variable at position i.
void setFirst()
Assign the first values to the tuple of the Instantiation.
const DiscreteVariable & variable(Idx i) const final
Returns the variable at position i in the tuple.
Exception : there is something wrong with an arc.
Exception: at least one argument passed to a function is not what was expected.
Exception : there is something wrong with an edge.
Generic doubly linked lists.
Val & front() const
Returns a reference to first element of a list, if any.
Val & pushBack(const Val &val)
Inserts a new element (a copy) at the end of the chained list.
bool empty() const noexcept
Returns a boolean indicating whether the chained list is empty.
void popFront()
Removes the first element of a List, if any.
Multidimensional matrix stored as an array in memory.
Idx nbrDim() const final
Returns the number of vars in the multidimensional container.
Size domainSize() const final
Returns the product of the variables domain size.
GUM_ELEMENT get(const Instantiation &i) const final
Default implementation of MultiDimContainer::get().
bool existsNode(const NodeId id) const
returns true iff the NodeGraphPart contains the given nodeId
virtual void addNodeWithId(const NodeId id)
try to insert a node with the given id
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
const iterator & end() const noexcept
void insert(const Key &k)
SequenceIterator< Key > const_iterator
Types for STL compliance.
bool contains(const Key &k) const
Indicates whether a given elements belong to the set.
bool empty() const noexcept
Indicates whether the set is the empty set.
void insert(const Key &k)
Inserts a new element into the set.
void erase(const Key &k)
Erases an element from the set.
aGrUM's Tensor is a multi-dimensional array with tensor operators.
Base class for undirected graphs.
const std::string & name() const
returns the name of the variable
#define GUM_ERROR(type, msg)
Builds a graph from a "fast" DOT-like textual description.
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Size Idx
Type for indexes.
Size NodeId
Type for node ids.
HashTable< NodeId, VAL > NodeProperty
Property on graph elements.
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 representing Influence Diagrams.
gum is the global namespace for all aGrUM entities
NodeId build_node_for_ID(gum::InfluenceDiagram< GUM_SCALAR > &infdiag, std::string node, std::string_view 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.