96 return e1.second > e2.second;
100 return std::abs(e1.second) > std::abs(e2.second);
105 double p1xz = std::get< 2 >(e1);
106 double p1yz = std::get< 3 >(e1);
107 double p2xz = std::get< 2 >(e2);
108 double p2yz = std::get< 3 >(e2);
109 double I1 = std::get< 1 >(e1);
110 double I2 = std::get< 1 >(e2);
111 if ((I1 < 0 && I2 < 0) || (I1 >= 0 && I2 >= 0)) {
112 if (std::max(p1xz, p1yz) == std::max(p2xz, p2yz)) {
113 return std::abs(I1) > std::abs(I2);
115 return std::max(p1xz, p1yz) > std::max(p2xz, p2yz);
168 HashTable< std::pair< NodeId, NodeId >, std::vector< NodeId > >& sepSet,
174 for (
const Edge& edge: edges) {
178 double Ixy = mutualInformation.
score(x, y);
181 graph.eraseEdge(edge);
184 "Remove " << x <<
" - " << y,
185 "Independent based on Mutual Information :" << Ixy)
186 sepSet.insert(std::make_pair(x, y),
_emptySet_);
191 "Keep " << x <<
" - " << y,
192 "Dependent based on Mutual Information :" << Ixy)
208 HashTable< std::pair< NodeId, NodeId >, std::vector< NodeId > >& sepSet,
215 while (rank.
top().second > 0.5) {
218 const NodeId x = std::get< 0 >(*(best.first));
219 const NodeId y = std::get< 1 >(*(best.first));
220 const NodeId z = std::get< 2 >(*(best.first));
221 std::vector< NodeId > ui = std::move(std::get< 3 >(*(best.first)));
224 const double i_xy_ui = mutualInformation.
score(x, y, ui);
229 "Remove " << x <<
" - " << y,
230 "Independent based on MutualInformation knowing Sep "
231 << ui <<
"Mutual information:" << i_xy_ui)
232 sepSet.insert(std::make_pair(x, y), std::move(ui));
260 const HashTable< std::pair< NodeId, NodeId >, std::vector< NodeId > >& sepSet) {
266 marks.
insert({arc.tail(), arc.head()},
'>');
267 marks.
insert({arc.head(), arc.tail()},
'-');
270 if (
graph.existsArc(arc.head(), arc.tail())) {
271 marks.
insert({arc.tail(), arc.head()},
'-');
272 marks.
insert({arc.head(), arc.tail()},
'>');
276 std::vector< ProbabilisticRanking > proba_triples
279 const Size steps_orient = proba_triples.size();
283 if (steps_orient > 0) best = proba_triples[0];
285 while (!proba_triples.empty() && std::max(std::get< 2 >(best), std::get< 3 >(best)) >= 0.5) {
286 const NodeId x = std::get< 0 >(*std::get< 0 >(best));
287 const NodeId y = std::get< 1 >(*std::get< 0 >(best));
288 const NodeId z = std::get< 2 >(*std::get< 0 >(best));
290 const double i3 = std::get< 1 >(best);
291 const double p1 = std::get< 2 >(best);
292 const double p2 = std::get< 3 >(best);
300 delete std::get< 0 >(best);
301 proba_triples.erase(proba_triples.begin());
304 if (!proba_triples.empty()) best = proba_triples[0];
316 graph.eraseArc(
Arc(iter->head(), iter->tail()));
318 graph.addArc(iter->head(), iter->tail());
319 graph.eraseArc(
Arc(iter->tail(), iter->head()));
320 *iter =
Arc(iter->head(), iter->tail());
332 HashTable< std::pair< NodeId, NodeId >,
char >& marks,
338 if (marks[{x, z}] ==
'o' && marks[{y, z}] ==
'o') {
343 GUM_SL_EMIT(x, z,
"Add Arc " << x <<
" -> " << z,
"V-structure Orientation")
355 GUM_SL_EMIT(z, x,
"Add Arc " << z <<
" -> " << x,
"V-structure Orientation")
365 GUM_SL_EMIT(y, z,
"Add Arc " << y <<
" -> " << z,
"V-structure Orientation")
377 GUM_SL_EMIT(z, y,
"Add Arc " << z <<
" -> " << y,
"V-structure Orientation")
382 }
else if (marks[{x, z}] ==
'>' && marks[{y, z}] ==
'o') {
389 "Add Arc " << y <<
" -> " << z,
390 "V-structure Orientation | existing "
391 << x <<
" -> " << z <<
", then orienting " << y <<
" -> " << z)
405 "Add Arc " << z <<
" -> " << y,
406 "V-structure Orientation | existing "
407 << x <<
" -> " << z <<
", then orienting " << z <<
" -> " << y)
412 }
else if (marks[{y, z}] ==
'>' && marks[{x, z}] ==
'o') {
417 GUM_SL_EMIT(x, z,
"Add Arc " << x <<
" -> " << z,
"V-structure Orientation")
429 GUM_SL_EMIT(z, x,
"Add Arc " << z <<
" -> " << x,
"V-structure Orientation")
442 HashTable< std::pair< NodeId, NodeId >,
char >& marks,
448 if (marks[{x, z}] ==
'>' && marks[{y, z}] ==
'o' && marks[{z, y}] !=
'-') {
455 "Add Arc " << z <<
" -> " << y,
456 "Propagation MIIC (919) | existing x -> " << z <<
" and " << z <<
" - "
465 GUM_SL_EMIT(y, z,
"Add Arc " << y <<
" -> " << z,
"Propagation MIIC line 932 ")
474 GUM_SL_EMIT(z, y,
"Add Arc " << z <<
"->" << y,
"Propagation MIIC 947 ")
482 GUM_SL_EMIT(z, y,
"Add Arc " << z <<
"->" << y,
"Propagation MIIC 959")
489 }
else if (marks[{y, z}] ==
'>' && marks[{x, z}] ==
'o' && marks[{z, x}] !=
'-') {
494 GUM_SL_EMIT(z, x,
"Add Arc " << z <<
" -> " << x,
"Propagation MIIC 977")
502 GUM_SL_EMIT(x, z,
"Add Arc " << x <<
"->" << z,
"Propagation MIIC 990")
511 GUM_SL_EMIT(z, x,
"Add Arc " << z <<
" -> " << x,
"Propagation MIIC 1004")
519 GUM_SL_EMIT(x, z,
"Add Arc " << x <<
" -> " << z,
"Propagation MIIC 1016")
535 const std::vector< NodeId >& ui,
542 const double Ixy_ui = mutualInformation.
score(x, y, ui);
545 if (z != x && z != y && std::find(ui.begin(), ui.end(), z) == ui.end()) {
549 const double Ixyz_ui = mutualInformation.
score(x, y, z, ui);
550 double calc_expo1 = -Ixyz_ui *
M_LN2;
553 }
else if (calc_expo1 < -
_maxLog_) {
556 Pnv = 1 / (1 + std::exp(calc_expo1));
559 const double Ixz_ui = mutualInformation.
score(x, z, ui);
560 const double Iyz_ui = mutualInformation.
score(y, z, ui);
562 calc_expo1 = -(Ixz_ui - Ixy_ui) *
M_LN2;
563 double calc_expo2 = -(Iyz_ui - Ixy_ui) *
M_LN2;
571 expo1 = (calc_expo1 < -
_maxLog_) ? 0.0 : std::exp(calc_expo1);
572 expo2 = (calc_expo2 < -
_maxLog_) ? 0.0 : std::exp(calc_expo2);
573 Pb = 1 / (1 + expo1 + expo2);
576 const double min_pnv_pb = std::min(Pnv, Pb);
577 if (min_pnv_pb > maxP) {
597 const HashTable< std::pair< NodeId, NodeId >, std::vector< NodeId > >& sepSet,
598 HashTable< std::pair< NodeId, NodeId >,
char >& marks) {
599 std::vector< ProbabilisticRanking > triples;
603 if (y < x && !
graph.existsEdge(x, y)) {
604 std::vector< NodeId > ui;
605 std::pair< NodeId, NodeId > key = {x, y};
606 std::pair< NodeId, NodeId > rev_key = {y, x};
607 if (sepSet.exists(key)) {
609 }
else if (sepSet.exists(rev_key)) {
610 ui = sepSet[rev_key];
612 const auto iter_z_place = std::find(ui.begin(), ui.end(), z);
613 if (iter_z_place != ui.end()) ui.erase(iter_z_place);
615 const double Ixyz_ui = mutualInformation.
score(x, y, z, ui);
618 triples.push_back(triple);
619 if (!marks.exists({x, z})) marks.insert({x, z},
'o');
620 if (!marks.exists({z, x})) marks.insert({z, x},
'o');
621 if (!marks.exists({y, z})) marks.insert({y, z},
'o');
622 if (!marks.exists({z, y})) marks.insert({z, y},
'o');
632 std::vector< ProbabilisticRanking >
634 std::vector< ProbabilisticRanking > probaTriples) {
635 for (
auto& triple: probaTriples) {
637 x = std::get< 0 >(*std::get< 0 >(triple));
638 y = std::get< 1 >(*std::get< 0 >(triple));
639 z = std::get< 2 >(*std::get< 0 >(triple));
640 const double Ixyz = std::get< 1 >(triple);
641 double Pxz = std::get< 2 >(triple);
642 double Pyz = std::get< 3 >(triple);
645 const double expo = std::exp(Ixyz);
646 const double P0 = (1 + expo) / (1 + 3 * expo);
647 if (Pxz == Pyz && Pyz == 0.5) {
648 std::get< 2 >(triple) = P0;
649 std::get< 3 >(triple) = P0;
651 if (
graph.existsArc(x, z) && Pxz >= P0) {
652 std::get< 3 >(triple) = Pxz * (1 / (1 + expo) - 0.5) + 0.5;
653 }
else if (
graph.existsArc(y, z) && Pyz >= P0) {
654 std::get< 2 >(triple) = Pyz * (1 / (1 + expo) - 0.5) + 0.5;
658 const double expo = std::exp(-Ixyz);
659 if (
graph.existsArc(x, z) && Pxz >= 0.5) {
660 std::get< 3 >(triple) = Pxz * (1 / (1 + expo) - 0.5) + 0.5;
661 }
else if (
graph.existsArc(y, z) && Pyz >= 0.5) {
662 std::get< 2 >(triple) = Pyz * (1 / (1 + expo) - 0.5) + 0.5;
677 return (std::find(lbeg, lend,
Arc(x, y)) == lend)
678 && (std::find(lbeg, lend,
Arc(y, x)) == lend);
#define GUM_SL_EMIT(x, y, action, explain)
Size current_step_
The current step.
The base class for all directed edges.
The base class for all undirected edges.
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.
Val pop()
Removes the top element from the heap and return it.
Size size() const noexcept
Returns the number of elements in the heap.
const Val & top() const
Returns the element at the top of the heap.
Size insert(const Val &val)
inserts a new element (actually a copy) in the heap and returns its index
Signaler< Size, double, double > onProgress
Progression, error and time.
Base class for mixed graphs.
Exception : a pointer or a reference on a nullptr (0) object.
Size size() const noexcept
Returns the number of elements in the set.
gum::DAG _mandatoryGraph_
gum::DiGraph _forbiddenGraph_
static bool _existsNonTrivialDirectedPath_(const MixedGraph &graph, NodeId n1, NodeId n2)
Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural cons...
gum::MeekRules meekRules_
Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural cons...
const std::vector< NodeId > _emptySet_
bool isArcValid_(const MixedGraph &graph, NodeId x, NodeId y)
HashTable< std::pair< NodeId, NodeId >, char > _initialMarks_
static bool _existsDirectedPath_(const MixedGraph &graph, NodeId n1, NodeId n2)
Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural cons...
ConstraintBasedLearning()
ConstraintBasedLearning & operator=(const ConstraintBasedLearning &)
void applyStructuralConstraints_(MixedGraph &graph)
Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural cons...
MixedGraph initGraph_(const MixedGraph &template_graph)
Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural cons...
std::vector< Arc > _latentCouples_
bool operator()(const Ranking &e1, const Ranking &e2) const
bool operator()(const CondRanking &e1, const CondRanking &e2) const
bool operator()(const ProbabilisticRanking &e1, const ProbabilisticRanking &e2) const
std::vector< ProbabilisticRanking > updateProbaTriples_(const MixedGraph &graph, std::vector< ProbabilisticRanking > probaTriples)
void _orientingVstructureMiic_(MixedGraph &graph, HashTable< std::pair< NodeId, NodeId >, char > &marks, NodeId x, NodeId y, NodeId z, double p1, double p2)
void orientationMiic_(CorrectedMutualInformation &mutualInformation, MixedGraph &graph, const HashTable< std::pair< NodeId, NodeId >, std::vector< NodeId > > &sepSet)
Miic & operator=(const Miic &from)
MixedGraph learnMixedStructure(MixedGraph graph) override
MixedGraph learnSkeleton(MixedGraph graph) override
void _propagatingOrientationMiic_(MixedGraph &graph, HashTable< std::pair< NodeId, NodeId >, char > &marks, NodeId x, NodeId y, NodeId z, double p1, double p2)
void iteration_(CorrectedMutualInformation &mutualInformation, MixedGraph &graph, HashTable< std::pair< NodeId, NodeId >, std::vector< NodeId > > &sepSet, Heap< CondRanking, GreaterPairOn2nd > &rank)
void findBestContributor_(NodeId x, NodeId y, const std::vector< NodeId > &ui, const MixedGraph &graph, CorrectedMutualInformation &mutualInformation, Heap< CondRanking, GreaterPairOn2nd > &rank)
std::vector< ProbabilisticRanking > unshieldedTriplesMiic_(const MixedGraph &graph, CorrectedMutualInformation &mutualInformation, const HashTable< std::pair< NodeId, NodeId >, std::vector< NodeId > > &sepSet, HashTable< std::pair< NodeId, NodeId >, char > &marks)
CorrectedMutualInformation * mi_
ArcProperty< double > _arcProbas_
void initiation_(CorrectedMutualInformation &mutualInformation, MixedGraph &graph, HashTable< std::pair< NodeId, NodeId >, std::vector< NodeId > > &sepSet, Heap< CondRanking, GreaterPairOn2nd > &rank)
void setMutualInformation(CorrectedMutualInformation &mi)
bool _isNotLatentCouple_(NodeId x, NodeId y)
#define GUM_ERROR(type, msg)
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Set< Edge > EdgeSet
Some typdefs and define for shortcuts ...
Size NodeId
Type for node ids.
Class hash tables iterators.
Base classes for mixed directed/undirected graphs.
include the inlined functions if necessary
std::pair< ThreePoints *, double > Ranking
std::pair< CondThreePoints *, double > CondRanking
std::tuple< NodeId, NodeId, NodeId, std::vector< NodeId > > CondThreePoints
std::tuple< NodeId, NodeId, NodeId > ThreePoints
std::tuple< ThreePoints *, double, double, double > ProbabilisticRanking
gum is the global namespace for all aGrUM entities
#define GUM_EMIT3(signal, arg1, arg2, arg3)
Class used to compute response times for benchmark purposes.