aGrUM 3.0.0
a C++ library for (probabilistic) graphical models
gum::learning::FCI Class Reference

Fast Causal Inference — PAG learning via constraint-based methods. More...

#include <FCI.h>

Inheritance diagram for gum::learning::FCI:
Collaboration diagram for gum::learning::FCI:

Public Types

enum class  UCPriority : uint8_t { Standard , Sorted }
 Controls how collider candidates are ordered before orientation. More...
enum class  ApproximationSchemeSTATE : char {
  Undefined , Continue , Epsilon , Rate ,
  Limit , TimeLimit , Stopped
}
 The different state of an approximation scheme. More...

Public Member Functions

Constructors / Destructors
 FCI ()
 FCI (const FCI &)=default
 FCI (FCI &&) noexcept
 ~FCI () override
FCIoperator= (const FCI &)
FCIoperator= (FCI &&) noexcept
FCI-specific parameterisation
void setMaxPathLength (Size maxLen)
 maximum path length for R4 discriminating-path search; Size(-1) = unlimited
Size maxPathLength () const
 maximum path length for R4 discriminating-path search; Size(-1) = unlimited
Learning
PAG learnPAG (MixedGraph graph)
 primary FCI output: learn a PAG from the given node-only or partial graph
MixedGraph learnMixedStructure (MixedGraph graph) override
 bridge for learnDAG/learnPDAG: runs learnPAG then converts via toMixedGraph()
std::vector< NodeIdpossibleDSep (const PAG &pag, NodeId x, NodeId y) const
 learnSkeleton() inherited from CIBasedLearning
CI test injection
void setIndependenceTest (IndependenceTest &test)
 inject independence test (non-owning: caller manages lifetime)
Parameterisation
void setAlpha (double alpha)
 maximum conditioning set size; Size(-1) = unlimited (default)
double alpha () const
 maximum conditioning set size; Size(-1) = unlimited (default)
void setMaxCondSetSize (Size max_k)
 maximum conditioning set size; Size(-1) = unlimited (default)
void setStable (bool stable)
 stable mode: defer edge removals until end of each depth (default: true)
void setExhaustiveSepSet (bool exhaustive)
 exhaustive sepset mode: accumulate union of all separating sets found at each depth, rather than stopping at the first (default: false)
bool exhaustiveSepSet () const
 maximum conditioning set size; Size(-1) = unlimited (default)
void setUCPriority (UCPriority p)
 collider candidate ordering (default: Standard)
UCPriority ucPriority () const
 maximum conditioning set size; Size(-1) = unlimited (default)
Learning
MixedGraph learnSkeleton (MixedGraph graph) override
 Phase 1: skeleton discovery via conditional independence tests.
Constraint setters
void setForbiddenGraph (const gum::DiGraph &forbidGraph)
void setMandatoryGraph (const gum::DAG &mandaGraph)
void setMaxIndegree (gum::Size n)
void addConstraints (const HashTable< std::pair< NodeId, NodeId >, char > &constraints)
const std::vector< ArclatentVariables () const
Learning — template methods (call the pure virtual interface)
PDAG learnPDAG (MixedGraph graph)
 learns the essential graph (CPDAG)
DAG learnDAG (MixedGraph graph)
 learns a DAG
template<GUM_Numeric GUM_SCALAR = double, typename PARAM_ESTIMATOR>
BayesNet< GUM_SCALAR > learnBN (PARAM_ESTIMATOR &estimator, MixedGraph graph)
 learns structure then estimates parameters
Getters and setters
void setEpsilon (double eps) override
 Given that we approximate f(t), stopping criterion on |f(t+1)-f(t)|.
double epsilon () const override
 Returns the value of epsilon.
void disableEpsilon () override
 Disable stopping criterion on epsilon.
void enableEpsilon () override
 Enable stopping criterion on epsilon.
bool isEnabledEpsilon () const override
 Returns true if stopping criterion on epsilon is enabled, false otherwise.
void setMinEpsilonRate (double rate) override
 Given that we approximate f(t), stopping criterion on d/dt(|f(t+1)-f(t)|).
double minEpsilonRate () const override
 Returns the value of the minimal epsilon rate.
void disableMinEpsilonRate () override
 Disable stopping criterion on epsilon rate.
void enableMinEpsilonRate () override
 Enable stopping criterion on epsilon rate.
bool isEnabledMinEpsilonRate () const override
 Returns true if stopping criterion on epsilon rate is enabled, false otherwise.
void setMaxIter (Size max) override
 Stopping criterion on number of iterations.
Size maxIter () const override
 Returns the criterion on number of iterations.
void disableMaxIter () override
 Disable stopping criterion on max iterations.
void enableMaxIter () override
 Enable stopping criterion on max iterations.
bool isEnabledMaxIter () const override
 Returns true if stopping criterion on max iterations is enabled, false otherwise.
void setMaxTime (double timeout) override
 Stopping criterion on timeout.
double maxTime () const override
 Returns the timeout (in seconds).
double currentTime () const override
 Returns the current running time in second.
void disableMaxTime () override
 Disable stopping criterion on timeout.
void enableMaxTime () override
 Enable stopping criterion on timeout.
bool isEnabledMaxTime () const override
 Returns true if stopping criterion on timeout is enabled, false otherwise.
void setPeriodSize (Size p) override
 How many samples between two stopping is enable.
Size periodSize () const override
 Returns the period size.
void setVerbosity (bool v) override
 Set the verbosity on (true) or off (false).
bool verbosity () const override
 Returns true if verbosity is enabled.
ApproximationSchemeSTATE stateApproximationScheme () const override
 Returns the approximation scheme state.
Size nbrIterations () const override
 Returns the number of iterations.
const std::vector< double > & history () const override
 Returns the scheme history.
void initApproximationScheme ()
 Initialise the scheme.
bool startOfPeriod () const
 Returns true if we are at the beginning of a period (compute error is mandatory).
void updateApproximationScheme (unsigned int incr=1)
 Update the scheme w.r.t the new error and increment steps.
Size remainingBurnIn () const
 Returns the remaining burn in.
void stopApproximationScheme ()
 Stop the approximation scheme.
bool continueApproximationScheme (double error)
 Update the scheme w.r.t the new error.
Getters and setters
std::string messageApproximationScheme () const
 Returns the approximation scheme message.

Public Attributes

Signaler< gum::NodeId, gum::NodeId, std::string, std::string > onStructuralModification
Signaler< Size, double, doubleonProgress
 Progression, error and time.
Signaler< std::string_view > onStop
 Criteria messageApproximationScheme.

Protected Member Functions

void resolveOrientConflict_ (NodeId src, NodeId dst) override
 conflict hook override: FCI leaves circle marks — orientation conflicts are not recorded as latent couples here (only final ↔ edges in Phase 6 are)
Collider orientation (shared between PC and FCI Phase 2/4)
MixedGraph orientUnshieldedColliders_ (MixedGraph graph)
 orient unshielded colliders in graph and return the updated graph
void orientColliderArm_ (MixedGraph &graph, NodeId src, NodeId dst)
 orient one arm (src → dst) of a collider; calls resolveOrientConflict_ on conflict
Constraint checks
bool isForbiddenArc_ (NodeId x, NodeId y) const
bool isForbiddenEdge_ (NodeId x, NodeId y) const
bool isMaxIndegree_ (const MixedGraph &graph, NodeId x)
bool isArcValid_ (const MixedGraph &graph, NodeId x, NodeId y)

Protected Attributes

double current_epsilon_
 Current epsilon.
double last_epsilon_
 Last epsilon value.
double current_rate_
 Current rate.
Size current_step_
 The current step.
Timer timer_
 The timer.
ApproximationSchemeSTATE current_state_
 The current state.
std::vector< doublehistory_
 The scheme history, used only if verbosity == true.
double eps_
 Threshold for convergence.
bool enabled_eps_
 If true, the threshold convergence is enabled.
double min_rate_eps_
 Threshold for the epsilon rate.
bool enabled_min_rate_eps_
 If true, the minimal threshold for epsilon rate is enabled.
double max_time_
 The timeout.
bool enabled_max_time_
 If true, the timeout is enabled.
Size max_iter_
 The maximum iterations.
bool enabled_max_iter_
 If true, the maximum iterations stopping criterion is enabled.
Size burn_in_
 Number of iterations before checking stopping criteria.
Size period_size_
 Checking criteria frequency.
bool verbosity_
 If true, verbosity is enabled.
Shared state
IndependenceTesttest_ {nullptr}
double alpha_ = 0.05
Size maxCondSetSize_ = Size(-1)
bool stable_ = true
bool exhaustiveSepSet_ = false
UCPriority ucPriority_ = UCPriority::Standard
HashTable< std::pair< NodeId, NodeId >, SepSetEntry_sepSet_

Private Member Functions

void orientCollidersOnPAG_ (PAG &pag, const MixedGraph &topology)
 Phase 2 / Phase 4: orient unshielded colliders directly on the PAG. topology is used for unshielded-triple detection (adjacency queries only).
std::vector< NodeIdcomputePossibleDSep_ (const PAG &pag, NodeId x, NodeId y) const
 Phase 3: return all nodes on possible-d-sep paths from x toward y (excl. x, y).
void possibleDSepPhase_ (PAG &pag)
 Phase 3: prune PAG edges using possibleDSep conditioning sets.
bool ruleR1_ (PAG &pag) const
 away from collider
bool ruleR2_ (PAG &pag) const
 away from cycle
bool ruleR3_ (PAG &pag) const
 double triangle
bool ruleR5_ (PAG &pag) const
 uncovered circle path → undirected
bool ruleR6_ (PAG &pag) const
 tail propagation from undirected edge
bool ruleR7_ (PAG &pag) const
 tail propagation from A-oB
bool ruleR4_ (PAG &pag) const
 discriminating path (uses CI test)
bool ruleR8_ (PAG &pag) const
 away from ancestor (graph only)
bool ruleR9_ (PAG &pag) const
 away from ancestor via uncovered pd-path
bool ruleR10_ (PAG &pag) const
 away from ancestor via two semi-directed paths
void applyOrientationRules_ (PAG &pag) const
 Phase 5: fixed-point loop over all orientation rules R1–R10.
bool doDdpOrientation_ (PAG &pag, NodeId d, NodeId a, NodeId b, NodeId c, const HashTable< NodeId, NodeId > &previous) const
 R4 helper: orient B,C in a detected discriminating path D..A,B,C.
void stopScheme_ (ApproximationSchemeSTATE new_state)
 Stop the scheme given a new state.

Private Attributes

Size maxPathLength_ = Size(-1)

Common state (accessible to subclasses)

gum::Size _maxIndegree_ {std::numeric_limits< gum::Size >::max()}
gum::DiGraph _forbiddenGraph_
gum::DAG _mandatoryGraph_
HashTable< std::pair< NodeId, NodeId >, char > _initialMarks_
std::vector< Arc_latentCouples_
int _maxLog_ {100}
const std::vector< NodeId_emptySet_

Graph utilities

void orientDoubleHeadedArcs_ (MixedGraph &mg)
 Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.
std::vector< ThreePointsunshieldedTriples_ (const MixedGraph &graph)
 Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.
void applyStructuralConstraints_ (MixedGraph &graph)
 Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.
MixedGraph initGraph_ (const MixedGraph &template_graph)
 Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.
gum::MeekRules meekRules_
 Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.
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 constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.
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 constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.

Detailed Description

Fast Causal Inference — PAG learning via constraint-based methods.

Phases:

  1. Skeleton discovery (inherited from CIBasedLearning)
  2. Initial PAG + unshielded colliders oriented as arrowheads
  3. possibleDSep pruning (Phase 3 — to be added in later step)
  4. Reset + re-orient colliders after possibleDSep (Phase 4 — later)
  5. Orientation rules R1–R10 (Phase 5 — later)
  6. Collect latentCouples from final PAG (Phase 6 — later)

learnMixedStructure() bridges to learnDAG/learnPDAG via toMixedGraph().

Definition at line 79 of file FCI.h.

Member Enumeration Documentation

◆ ApproximationSchemeSTATE

The different state of an approximation scheme.

Enumerator
Undefined 
Continue 
Epsilon 
Rate 
Limit 
TimeLimit 
Stopped 

Definition at line 87 of file IApproximationSchemeConfiguration.h.

87 : char {
88 Undefined,
89 Continue,
90 Epsilon,
91 Rate,
92 Limit,
93 TimeLimit,
94 Stopped
95 };

◆ UCPriority

enum class gum::learning::CIBasedLearning::UCPriority : uint8_t
stronginherited

Controls how collider candidates are ordered before orientation.

Enumerator
Standard 

process triples in natural traversal order

Sorted 

descending p-value order (strongest evidence first)

Definition at line 84 of file CIBasedLearning.h.

84 : uint8_t {
85 Standard,
86 Sorted,
87 };

Constructor & Destructor Documentation

◆ FCI() [1/3]

gum::learning::FCI::FCI ( )
default

Referenced by FCI(), FCI(), ~FCI(), operator=(), and operator=().

Here is the caller graph for this function:

◆ FCI() [2/3]

gum::learning::FCI::FCI ( const FCI & )
default

References FCI().

Here is the call graph for this function:

◆ FCI() [3/3]

gum::learning::FCI::FCI ( FCI && from)
noexcept

Definition at line 59 of file FCI.cpp.

59 :
60 CIBasedLearning(std::move(from)), maxPathLength_(from.maxPathLength_) {}
Size maxPathLength_
Definition FCI.h:165

References gum::learning::CIBasedLearning::CIBasedLearning(), FCI(), and maxPathLength_.

Here is the call graph for this function:

◆ ~FCI()

gum::learning::FCI::~FCI ( )
overridedefault

Member Function Documentation

◆ _existsDirectedPath_()

bool gum::learning::ConstraintBasedLearning::_existsDirectedPath_ ( const MixedGraph & graph,
NodeId n1,
NodeId n2 )
staticprotectedinherited

Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.

Definition at line 180 of file ConstraintBasedLearning.cpp.

182 {
183 List< NodeId > nodeFIFO;
184 Set< NodeId > mark;
185
186 mark.insert(n2);
187 nodeFIFO.pushBack(n2);
188
189 NodeId current;
190 while (!nodeFIFO.empty()) {
191 current = nodeFIFO.front();
192 nodeFIFO.popFront();
193 for (const auto new_one: graph.parents(current)) {
194 if (graph.existsArc(current, new_one)) continue; // double arc — skip
195 if (new_one == n1) return true;
196 if (mark.exists(new_one)) continue;
197 mark.insert(new_one);
198 nodeFIFO.pushBack(new_one);
199 }
200 }
201 return false;
202 }
Size NodeId
Type for node ids.

References gum::List< Val >::empty(), gum::Set< Key >::exists(), gum::List< Val >::front(), gum::Set< Key >::insert(), gum::List< Val >::popFront(), and gum::List< Val >::pushBack().

Referenced by _existsNonTrivialDirectedPath_(), gum::learning::Miic::_propagatingOrientationMiic_(), gum::learning::Miic::orientationMiic_(), gum::learning::CIBasedLearning::orientColliderArm_(), and orientDoubleHeadedArcs_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _existsNonTrivialDirectedPath_()

bool gum::learning::ConstraintBasedLearning::_existsNonTrivialDirectedPath_ ( const MixedGraph & graph,
NodeId n1,
NodeId n2 )
staticprotectedinherited

Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.

Definition at line 169 of file ConstraintBasedLearning.cpp.

171 {
172 for (const auto parent: graph.parents(n2)) {
173 if (graph.existsArc(n2, parent)) continue; // double arc — skip
174 if (parent == n1) continue; // trivial path — not counted
175 if (_existsDirectedPath_(graph, n1, parent)) return true;
176 }
177 return false;
178 }
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...

References _existsDirectedPath_().

Referenced by gum::learning::Miic::_orientingVstructureMiic_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ addConstraints()

void gum::learning::ConstraintBasedLearning::addConstraints ( const HashTable< std::pair< NodeId, NodeId >, char > & constraints)
inherited

Definition at line 124 of file ConstraintBasedLearning.cpp.

125 {
126 _initialMarks_ = constraints;
127 }
HashTable< std::pair< NodeId, NodeId >, char > _initialMarks_

References _initialMarks_.

◆ alpha()

double gum::learning::CIBasedLearning::alpha ( ) const
inherited

maximum conditioning set size; Size(-1) = unlimited (default)

Definition at line 108 of file CIBasedLearning.cpp.

References alpha_.

Referenced by ~CIBasedLearning(), and setAlpha().

Here is the caller graph for this function:

◆ applyOrientationRules_()

void gum::learning::FCI::applyOrientationRules_ ( PAG & pag) const
private

Phase 5: fixed-point loop over all orientation rules R1–R10.

Definition at line 797 of file FCI.cpp.

797 {
798 bool changed = true;
799 while (changed) {
800 changed = false;
801 changed |= ruleR1_(pag);
802 changed |= ruleR2_(pag);
803 changed |= ruleR3_(pag);
804 changed |= ruleR4_(pag);
805 changed |= ruleR5_(pag);
806 changed |= ruleR6_(pag);
807 changed |= ruleR7_(pag);
808 changed |= ruleR8_(pag);
809 changed |= ruleR9_(pag);
810 changed |= ruleR10_(pag);
811 }
812 }
bool ruleR7_(PAG &pag) const
tail propagation from A-oB
Definition FCI.cpp:512
bool ruleR1_(PAG &pag) const
away from collider
Definition FCI.cpp:354
bool ruleR3_(PAG &pag) const
double triangle
Definition FCI.cpp:405
bool ruleR5_(PAG &pag) const
uncovered circle path → undirected
Definition FCI.cpp:449
bool ruleR9_(PAG &pag) const
away from ancestor via uncovered pd-path
Definition FCI.cpp:719
bool ruleR6_(PAG &pag) const
tail propagation from undirected edge
Definition FCI.cpp:489
bool ruleR8_(PAG &pag) const
away from ancestor (graph only)
Definition FCI.cpp:693
bool ruleR2_(PAG &pag) const
away from cycle
Definition FCI.cpp:378
bool ruleR4_(PAG &pag) const
discriminating path (uses CI test)
Definition FCI.cpp:595
bool ruleR10_(PAG &pag) const
away from ancestor via two semi-directed paths
Definition FCI.cpp:744

References ruleR10_(), ruleR1_(), ruleR2_(), ruleR3_(), ruleR4_(), ruleR5_(), ruleR6_(), ruleR7_(), ruleR8_(), and ruleR9_().

Referenced by ~FCI(), and learnPAG().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ applyStructuralConstraints_()

void gum::learning::ConstraintBasedLearning::applyStructuralConstraints_ ( MixedGraph & graph)
protectedinherited

Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.

Definition at line 250 of file ConstraintBasedLearning.cpp.

250 {
251 for (const auto& arc: _mandatoryGraph_.arcs()) {
252 if (graph.existsEdge(arc.head(), arc.tail())) graph.eraseEdge(Edge(arc.head(), arc.tail()));
253 if (!graph.existsArc(arc.tail(), arc.head())) {
254 GUM_SL_EMIT(arc.tail(),
255 arc.head(),
256 "Add Arc" << arc.tail() << "->" << arc.head(),
257 "Mandatory")
258 graph.addArc(arc.tail(), arc.head());
259 }
260 }
261 for (const Arc& arc: _forbiddenGraph_.arcs()) {
262 if (graph.existsEdge(Edge(arc.tail(), arc.head()))) {
263 graph.eraseEdge(Edge(arc.tail(), arc.head()));
264 graph.addArc(arc.head(), arc.tail());
265 GUM_SL_EMIT(arc.head(),
266 arc.tail(),
267 "Add Arc" << arc.head() << "->" << arc.tail(),
268 "Forbidden in the other orientation")
269 }
270 }
271 }
#define GUM_SL_EMIT(x, y, action, explain)

References _forbiddenGraph_, _mandatoryGraph_, and GUM_SL_EMIT.

Referenced by gum::learning::PC::learnMixedStructure(), gum::learning::FCI::learnPAG(), and gum::learning::Miic::orientationMiic_().

Here is the caller graph for this function:

◆ computePossibleDSep_()

std::vector< NodeId > gum::learning::FCI::computePossibleDSep_ ( const PAG & pag,
NodeId x,
NodeId y ) const
private

Phase 3: return all nodes on possible-d-sep paths from x toward y (excl. x, y).

Definition at line 248 of file FCI.cpp.

248 {
249 std::set< NodeId > result;
250 std::queue< std::pair< NodeId, NodeId > > bfsQueue;
251 std::set< std::pair< NodeId, NodeId > > visited;
252
253 for (const NodeId b: pag.neighbours(x)) {
254 if (b == y) { continue; }
255 if (visited.insert({x, b}).second) {
256 bfsQueue.emplace(x, b);
257 result.insert(b);
258 }
259 }
260
261 while (!bfsQueue.empty()) {
262 const auto [a, b] = bfsQueue.front();
263 bfsQueue.pop();
264
265 for (const NodeId c: pag.neighbours(b)) {
266 if (c == x || c == y || c == a) { continue; }
267 // expand if B is a definite collider on (A, B, C) or A and C are adjacent
268 // (Zhang 2008 / Colombo et al. criterion)
269 if (pag.isDefCollider(a, b, c) || pag.existsEdge(a, c)) {
270 if (visited.insert({b, c}).second) {
271 bfsQueue.emplace(b, c);
272 // FIX #3: only add c to PossibleDSep if it has a semi-directed path
273 // back toward x or b (Zhang 2008 §3.2 filter).
274 if (existsSemiDirectedPath_(pag, c, x) || existsSemiDirectedPath_(pag, c, b)) {
275 result.insert(c);
276 }
277 }
278 }
279 }
280 }
281
282 result.erase(x);
283 result.erase(y);
284 return {result.begin(), result.end()};
285 }

References gum::EdgeGraphPart::existsEdge(), gum::PAG::isDefCollider(), and gum::EdgeGraphPart::neighbours().

Referenced by ~FCI(), possibleDSep(), and possibleDSepPhase_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ continueApproximationScheme()

bool gum::ApproximationScheme::continueApproximationScheme ( double error)
inherited

Update the scheme w.r.t the new error.

Test the stopping criterion that are enabled.

Parameters
errorThe new error value.
Returns
false if state become != ApproximationSchemeSTATE::Continue
Exceptions
OperationNotAllowedRaised if state != ApproximationSchemeSTATE::Continue.

Definition at line 69 of file approximationScheme.cpp.

69 {
70 // For coherence, we fix the time used in the method
71
72 double timer_step = timer_.step();
73
75 if (timer_step > max_time_) {
77 return false;
78 }
79 }
80
81 if (!startOfPeriod()) { return true; }
82
85 OperationNotAllowed,
86 "state of the approximation scheme is not correct : " << messageApproximationScheme());
87 }
88
89 if (verbosity()) { history_.push_back(error); }
90
92 if (current_step_ >= max_iter_) {
94 return false;
95 }
96 }
97
99 current_epsilon_ = error; // eps rate isEnabled needs it so affectation was
100 // moved from eps isEnabled below
101
102 if (enabled_eps_) {
103 if (current_epsilon_ <= eps_) {
105 return false;
106 }
107 }
108
109 if (last_epsilon_ >= 0.) {
110 if (current_epsilon_ > .0) {
111 // ! current_epsilon_ can be 0. AND epsilon
112 // isEnabled can be disabled !
114 }
115 // limit with current eps ---> 0 is | 1 - ( last_eps / 0 ) | --->
116 // infinity the else means a return false if we isEnabled the rate below,
117 // as we would have returned false if epsilon isEnabled was enabled
118 else {
120 }
121
125 return false;
126 }
127 }
128 }
129
131 if (onProgress.hasListener()) {
133 }
134
135 return true;
136 } else {
137 return false;
138 }
139 }
Size current_step_
The current step.
double current_epsilon_
Current epsilon.
double last_epsilon_
Last epsilon value.
double eps_
Threshold for convergence.
bool enabled_max_time_
If true, the timeout is enabled.
Size max_iter_
The maximum iterations.
bool enabled_eps_
If true, the threshold convergence is enabled.
ApproximationSchemeSTATE current_state_
The current state.
double min_rate_eps_
Threshold for the epsilon rate.
std::vector< double > history_
The scheme history, used only if verbosity == true.
double current_rate_
Current rate.
ApproximationSchemeSTATE stateApproximationScheme() const override
Returns the approximation scheme state.
bool startOfPeriod() const
Returns true if we are at the beginning of a period (compute error is mandatory).
bool enabled_max_iter_
If true, the maximum iterations stopping criterion is enabled.
void stopScheme_(ApproximationSchemeSTATE new_state)
Stop the scheme given a new state.
bool verbosity() const override
Returns true if verbosity is enabled.
bool enabled_min_rate_eps_
If true, the minimal threshold for epsilon rate is enabled.
Signaler< Size, double, double > onProgress
Progression, error and time.
std::string messageApproximationScheme() const
Returns the approximation scheme message.
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
#define GUM_EMIT3(signal, arg1, arg2, arg3)
Definition signaler.h:291

References gum::IApproximationSchemeConfiguration::Continue, current_epsilon_, current_rate_, current_state_, current_step_, enabled_eps_, enabled_max_iter_, enabled_max_time_, enabled_min_rate_eps_, eps_, gum::IApproximationSchemeConfiguration::Epsilon, GUM_EMIT3, GUM_ERROR, history_, last_epsilon_, gum::IApproximationSchemeConfiguration::Limit, max_iter_, max_time_, gum::IApproximationSchemeConfiguration::messageApproximationScheme(), min_rate_eps_, gum::IApproximationSchemeConfiguration::onProgress, gum::IApproximationSchemeConfiguration::Rate, startOfPeriod(), stateApproximationScheme(), stopScheme_(), gum::IApproximationSchemeConfiguration::TimeLimit, timer_, and verbosity().

Referenced by gum::GibbsBNdistance< GUM_SCALAR >::computeKL_(), gum::learning::GreedyHillClimbing::learnStructure(), gum::learning::GreedyThickThinning::learnStructure(), gum::learning::LocalSearchWithTabuList::learnStructure(), gum::SamplingInference< GUM_SCALAR >::loopApproxInference_(), gum::credal::CNLoopyPropagation< GUM_SCALAR >::makeInferenceByOrderedArcs_(), gum::credal::CNLoopyPropagation< GUM_SCALAR >::makeInferenceByRandomOrder_(), and gum::credal::CNLoopyPropagation< GUM_SCALAR >::makeInferenceNodeToNeighbours_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ currentTime()

INLINE double gum::ApproximationScheme::currentTime ( ) const
overridevirtualinherited

Returns the current running time in second.

Returns
Returns the current running time in second.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 137 of file approximationScheme_inl.h.

137{ return timer_.step(); }

References timer_.

◆ disableEpsilon()

INLINE void gum::ApproximationScheme::disableEpsilon ( )
overridevirtualinherited

Disable stopping criterion on epsilon.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 75 of file approximationScheme_inl.h.

75{ enabled_eps_ = false; }

References enabled_eps_.

Referenced by gum::learning::EMApproximationScheme::EMApproximationScheme(), and gum::learning::EMApproximationScheme::setMinEpsilonRate().

Here is the caller graph for this function:

◆ disableMaxIter()

INLINE void gum::ApproximationScheme::disableMaxIter ( )
overridevirtualinherited

Disable stopping criterion on max iterations.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 116 of file approximationScheme_inl.h.

116{ enabled_max_iter_ = false; }

References enabled_max_iter_.

Referenced by gum::learning::GreedyHillClimbing::GreedyHillClimbing(), and gum::learning::GreedyThickThinning::GreedyThickThinning().

Here is the caller graph for this function:

◆ disableMaxTime()

INLINE void gum::ApproximationScheme::disableMaxTime ( )
overridevirtualinherited

Disable stopping criterion on timeout.

Returns
Disable stopping criterion on timeout.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 140 of file approximationScheme_inl.h.

140{ enabled_max_time_ = false; }

References enabled_max_time_.

Referenced by gum::learning::GreedyHillClimbing::GreedyHillClimbing(), and gum::learning::GreedyThickThinning::GreedyThickThinning().

Here is the caller graph for this function:

◆ disableMinEpsilonRate()

INLINE void gum::ApproximationScheme::disableMinEpsilonRate ( )
overridevirtualinherited

Disable stopping criterion on epsilon rate.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 96 of file approximationScheme_inl.h.

96{ enabled_min_rate_eps_ = false; }

References enabled_min_rate_eps_.

Referenced by gum::learning::GreedyHillClimbing::GreedyHillClimbing(), gum::learning::GreedyThickThinning::GreedyThickThinning(), gum::GibbsBNdistance< GUM_SCALAR >::computeKL_(), and gum::learning::EMApproximationScheme::setEpsilon().

Here is the caller graph for this function:

◆ doDdpOrientation_()

bool gum::learning::FCI::doDdpOrientation_ ( PAG & pag,
NodeId d,
NodeId a,
NodeId b,
NodeId c,
const HashTable< NodeId, NodeId > & previous ) const
private

R4 helper: orient B,C in a detected discriminating path D..A,B,C.

Definition at line 539 of file FCI.cpp.

544 {
545 // Reconstruct conditioning set: follow previous from d toward b
546 std::vector< NodeId > path;
547 NodeId cur = d;
548 while (previous.exists(cur)) {
549 cur = previous[cur];
550 path.push_back(cur);
551 }
552 // path = [previous[d], ..., b]
553
554 const double pval1 = test_->statistics(d, c, path).second;
555 const bool ind1 = pval1 > alpha_;
556
557 std::vector< NodeId > path_no_b;
558 for (const NodeId n: path) {
559 if (n != b) { path_no_b.push_back(n); }
560 }
561 const double pval2 = test_->statistics(d, c, path_no_b).second;
562 const bool ind2 = pval2 > alpha_;
563
564 bool use_b_in_sep;
565 if (!ind1 && !ind2) {
566 // fall back to existing sepSet
567 const bool has_dc = sepSet_.exists({d, c});
568 const bool has_cd = sepSet_.exists({c, d});
569 if (!has_dc && !has_cd) { return false; }
570 const auto& cond = has_dc ? sepSet_[{d, c}].cond : sepSet_[{c, d}].cond;
571 use_b_in_sep = (std::ranges::find(cond, b) != cond.end());
572 } else {
573 use_b_in_sep = ind1;
574 }
575
576 if (use_b_in_sep) {
577 pag.setMarkAt(c, b, EdgeMark::Tail); // B→C: tail at B from C
578 return true;
579 }
580 bool any = false;
581 if (!isForbiddenArc_(a, b)) {
582 pag.setMarkAt(a, b, EdgeMark::Arrowhead);
583 any = true;
584 }
585 if (!isForbiddenArc_(c, b)) {
586 pag.setMarkAt(c, b, EdgeMark::Arrowhead);
587 any = true;
588 }
589 return any;
590 }
HashTable< std::pair< NodeId, NodeId >, SepSetEntry_ > sepSet_
@ Arrowhead
Definition PAG.h:65

References gum::learning::CIBasedLearning::alpha_, gum::Arrowhead, gum::HashTable< Key, Val >::exists(), gum::learning::ConstraintBasedLearning::isForbiddenArc_(), gum::learning::CIBasedLearning::sepSet_, gum::PAG::setMarkAt(), gum::Tail, and gum::learning::CIBasedLearning::test_.

Referenced by ~FCI(), and ruleR4_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ enableEpsilon()

INLINE void gum::ApproximationScheme::enableEpsilon ( )
overridevirtualinherited

Enable stopping criterion on epsilon.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 78 of file approximationScheme_inl.h.

78{ enabled_eps_ = true; }

References enabled_eps_.

◆ enableMaxIter()

INLINE void gum::ApproximationScheme::enableMaxIter ( )
overridevirtualinherited

Enable stopping criterion on max iterations.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 119 of file approximationScheme_inl.h.

119{ enabled_max_iter_ = true; }

References enabled_max_iter_.

◆ enableMaxTime()

INLINE void gum::ApproximationScheme::enableMaxTime ( )
overridevirtualinherited

Enable stopping criterion on timeout.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 143 of file approximationScheme_inl.h.

143{ enabled_max_time_ = true; }

References enabled_max_time_.

◆ enableMinEpsilonRate()

INLINE void gum::ApproximationScheme::enableMinEpsilonRate ( )
overridevirtualinherited

Enable stopping criterion on epsilon rate.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 99 of file approximationScheme_inl.h.

99{ enabled_min_rate_eps_ = true; }

References enabled_min_rate_eps_.

Referenced by gum::learning::EMApproximationScheme::EMApproximationScheme(), and gum::GibbsBNdistance< GUM_SCALAR >::computeKL_().

Here is the caller graph for this function:

◆ epsilon()

INLINE double gum::ApproximationScheme::epsilon ( ) const
overridevirtualinherited

Returns the value of epsilon.

Returns
Returns the value of epsilon.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 72 of file approximationScheme_inl.h.

72{ return eps_; }

References eps_.

Referenced by gum::ImportanceSampling< GUM_SCALAR >::onContextualize_(), and gum::ImportanceSampling< GUM_SCALAR >::unsharpenBN_().

Here is the caller graph for this function:

◆ exhaustiveSepSet()

bool gum::learning::CIBasedLearning::exhaustiveSepSet ( ) const
inherited

maximum conditioning set size; Size(-1) = unlimited (default)

Definition at line 116 of file CIBasedLearning.cpp.

References exhaustiveSepSet_.

Referenced by ~CIBasedLearning().

Here is the caller graph for this function:

◆ history()

INLINE const std::vector< double > & gum::ApproximationScheme::history ( ) const
overridevirtualinherited

Returns the scheme history.

Returns
Returns the scheme history.
Exceptions
OperationNotAllowedRaised if the scheme did not performed or if verbosity is set to false.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 179 of file approximationScheme_inl.h.

179 {
181 GUM_ERROR(OperationNotAllowed, "state of the approximation scheme is udefined")
182 }
183
184 if (!verbosity()) GUM_ERROR(OperationNotAllowed, "No history when verbosity=false")
185
186 return history_;
187 }

References GUM_ERROR, stateApproximationScheme(), and gum::IApproximationSchemeConfiguration::Undefined.

Here is the call graph for this function:

◆ initApproximationScheme()

INLINE void gum::ApproximationScheme::initApproximationScheme ( )
inherited

Initialise the scheme.

Definition at line 190 of file approximationScheme_inl.h.

190 {
192 current_step_ = 0;
194 history_.clear();
195 timer_.reset();
196 }

References ApproximationScheme(), gum::IApproximationSchemeConfiguration::Continue, current_state_, current_step_, and initApproximationScheme().

Referenced by gum::GibbsBNdistance< GUM_SCALAR >::computeKL_(), initApproximationScheme(), gum::learning::GreedyHillClimbing::learnStructure(), gum::learning::GreedyThickThinning::learnStructure(), gum::learning::LocalSearchWithTabuList::learnStructure(), gum::SamplingInference< GUM_SCALAR >::loopApproxInference_(), gum::credal::CNLoopyPropagation< GUM_SCALAR >::makeInference(), and gum::SamplingInference< GUM_SCALAR >::onStateChanged_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ initGraph_()

MixedGraph gum::learning::ConstraintBasedLearning::initGraph_ ( const MixedGraph & template_graph)
protectedinherited

Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.

Definition at line 273 of file ConstraintBasedLearning.cpp.

273 {
274 MixedGraph graph;
275 for (NodeId n: template_graph.nodes())
276 graph.addNodeWithId(n);
277
278 auto addEdgeIfAllowed = [&](NodeId x, NodeId y) {
279 if (x > y) std::swap(x, y);
280 if (isForbiddenEdge_(x, y))
281 GUM_SL_EMIT(x, y, "Remove " << x << " - " << y, "Constraints : Forbidden edge")
282 else graph.addEdge(x, y);
283 };
284
285 if (template_graph.edges().empty()) {
286 // node-only template: constraint-based learning always starts from complete graph
287 const std::vector< NodeId > nodes(template_graph.nodes().begin(),
288 template_graph.nodes().end());
289 for (std::size_t i = 0; i < nodes.size(); ++i)
290 for (std::size_t j = i + 1; j < nodes.size(); ++j)
291 addEdgeIfAllowed(nodes[i], nodes[j]);
292 } else {
293 for (const auto& edge: template_graph.edges())
294 addEdgeIfAllowed(edge.first(), edge.second());
295 }
296
297 return graph;
298 }
bool isForbiddenEdge_(NodeId x, NodeId y) const

References gum::NodeGraphPart::begin(), gum::EdgeGraphPart::edges(), gum::Set< Key >::empty(), gum::NodeGraphPart::end(), GUM_SL_EMIT, isForbiddenEdge_(), and gum::NodeGraphPart::nodes().

Referenced by gum::learning::Miic::learnMixedStructure(), gum::learning::CIBasedLearning::learnSkeleton(), and gum::learning::Miic::learnSkeleton().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isArcValid_()

bool gum::learning::ConstraintBasedLearning::isArcValid_ ( const MixedGraph & graph,
NodeId x,
NodeId y )
protectedinherited

Definition at line 161 of file ConstraintBasedLearning.cpp.

161 {
162 return !isForbiddenArc_(x, y) && !isMaxIndegree_(graph, y);
163 }
bool isMaxIndegree_(const MixedGraph &graph, NodeId x)

References isForbiddenArc_(), and isMaxIndegree_().

Referenced by gum::learning::Miic::_orientingVstructureMiic_(), gum::learning::Miic::_propagatingOrientationMiic_(), and gum::learning::CIBasedLearning::orientColliderArm_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ isEnabledEpsilon()

INLINE bool gum::ApproximationScheme::isEnabledEpsilon ( ) const
overridevirtualinherited

Returns true if stopping criterion on epsilon is enabled, false otherwise.

Returns
Returns true if stopping criterion on epsilon is enabled, false otherwise.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 82 of file approximationScheme_inl.h.

82{ return enabled_eps_; }

References enabled_eps_.

◆ isEnabledMaxIter()

INLINE bool gum::ApproximationScheme::isEnabledMaxIter ( ) const
overridevirtualinherited

Returns true if stopping criterion on max iterations is enabled, false otherwise.

Returns
Returns true if stopping criterion on max iterations is enabled, false otherwise.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 123 of file approximationScheme_inl.h.

123{ return enabled_max_iter_; }

References enabled_max_iter_.

◆ isEnabledMaxTime()

INLINE bool gum::ApproximationScheme::isEnabledMaxTime ( ) const
overridevirtualinherited

Returns true if stopping criterion on timeout is enabled, false otherwise.

Returns
Returns true if stopping criterion on timeout is enabled, false otherwise.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 147 of file approximationScheme_inl.h.

147{ return enabled_max_time_; }

References enabled_max_time_.

◆ isEnabledMinEpsilonRate()

INLINE bool gum::ApproximationScheme::isEnabledMinEpsilonRate ( ) const
overridevirtualinherited

Returns true if stopping criterion on epsilon rate is enabled, false otherwise.

Returns
Returns true if stopping criterion on epsilon rate is enabled, false otherwise.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 103 of file approximationScheme_inl.h.

103{ return enabled_min_rate_eps_; }

References enabled_min_rate_eps_.

Referenced by gum::GibbsBNdistance< GUM_SCALAR >::computeKL_().

Here is the caller graph for this function:

◆ isForbiddenArc_()

bool gum::learning::ConstraintBasedLearning::isForbiddenArc_ ( NodeId x,
NodeId y ) const
protectedinherited

Definition at line 149 of file ConstraintBasedLearning.cpp.

149 {
150 return _forbiddenGraph_.existsArc(x, y);
151 }

References _forbiddenGraph_.

Referenced by gum::learning::FCI::doDdpOrientation_(), isArcValid_(), gum::learning::FCI::orientCollidersOnPAG_(), gum::learning::FCI::ruleR1_(), and gum::learning::FCI::ruleR2_().

Here is the caller graph for this function:

◆ isForbiddenEdge_()

bool gum::learning::ConstraintBasedLearning::isForbiddenEdge_ ( NodeId x,
NodeId y ) const
protectedinherited

Definition at line 153 of file ConstraintBasedLearning.cpp.

153 {
154 return _forbiddenGraph_.existsArc(x, y) && _forbiddenGraph_.existsArc(y, x);
155 }

References _forbiddenGraph_.

Referenced by initGraph_().

Here is the caller graph for this function:

◆ isMaxIndegree_()

bool gum::learning::ConstraintBasedLearning::isMaxIndegree_ ( const MixedGraph & graph,
NodeId x )
protectedinherited

Definition at line 157 of file ConstraintBasedLearning.cpp.

157 {
158 return graph.parents(x).size() >= _maxIndegree_;
159 }

References _maxIndegree_.

Referenced by isArcValid_().

Here is the caller graph for this function:

◆ latentVariables()

const std::vector< Arc > gum::learning::ConstraintBasedLearning::latentVariables ( ) const
inherited

Definition at line 129 of file ConstraintBasedLearning.cpp.

129 {
130 return _latentCouples_;
131 }

References _latentCouples_.

◆ learnBN()

template<GUM_Numeric GUM_SCALAR, typename PARAM_ESTIMATOR>
BayesNet< GUM_SCALAR > gum::learning::ConstraintBasedLearning::learnBN ( PARAM_ESTIMATOR & estimator,
MixedGraph graph )
inherited

learns structure then estimates parameters

Definition at line 12 of file ConstraintBasedLearning_tpl.h.

13 {
14 return DAG2BNLearner::createBN< GUM_SCALAR >(estimator, learnDAG(graph));
15 }
DAG learnDAG(MixedGraph graph)
learns a DAG
static BayesNet< GUM_SCALAR > createBN(ParamEstimator &estimator, const DAG &dag)
create a BN from a DAG using a one pass generator (typically ML)

References gum::learning::DAG2BNLearner::createBN(), and learnDAG().

Here is the call graph for this function:

◆ learnDAG()

DAG gum::learning::ConstraintBasedLearning::learnDAG ( MixedGraph graph)
inherited

learns a DAG

Definition at line 141 of file ConstraintBasedLearning.cpp.

141 {
142 return meekRules_.propagateToDAG(learnMixedStructure(graph));
143 }
gum::MeekRules meekRules_
Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural cons...
virtual MixedGraph learnMixedStructure(MixedGraph graph)=0

References learnMixedStructure(), and meekRules_.

Referenced by learnBN().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ learnMixedStructure()

MixedGraph gum::learning::FCI::learnMixedStructure ( MixedGraph graph)
overridevirtual

bridge for learnDAG/learnPDAG: runs learnPAG then converts via toMixedGraph()

Implements gum::learning::ConstraintBasedLearning.

Definition at line 871 of file FCI.cpp.

871 {
872 PAG pag = learnPAG(std::move(graph));
873 MixedGraph mg = pag.toMixedGraph();
875 return mg;
876 }
void orientDoubleHeadedArcs_(MixedGraph &mg)
Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural cons...
PAG learnPAG(MixedGraph graph)
primary FCI output: learn a PAG from the given node-only or partial graph
Definition FCI.cpp:818

References learnPAG(), gum::learning::ConstraintBasedLearning::orientDoubleHeadedArcs_(), and gum::PAG::toMixedGraph().

Referenced by ~FCI().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ learnPAG()

PAG gum::learning::FCI::learnPAG ( MixedGraph graph)

primary FCI output: learn a PAG from the given node-only or partial graph

Definition at line 818 of file FCI.cpp.

818 {
819 // Phase 1: skeleton discovery
820 MixedGraph skeleton = learnSkeleton(std::move(graph));
822
823 // Build initial PAG from skeleton
824 PAG pag;
825 for (const NodeId n: skeleton.nodes()) {
826 pag.addNodeWithId(n);
827 }
828 // undirected skeleton edges → Circle-Circle
829 for (const Edge& e: skeleton.edges()) {
830 pag.addEdge(e.first(), e.second());
831 }
832 // mandatory arcs → Tail-Arrowhead
833 for (const Arc& a: skeleton.arcs()) {
834 pag.addEdge(a.tail(), a.head(), EdgeMark::Tail, EdgeMark::Arrowhead);
835 }
836
837 // Phase 2: orient unshielded colliders on PAG
838 orientCollidersOnPAG_(pag, skeleton);
839
840 // Phase 3: possibleDSep pruning
842
843 // Phase 4: reset marks to Circle, restore mandatory arcs, re-orient colliders
844 pag.reorientAllWith(EdgeMark::Circle);
845 for (const Arc& a: skeleton.arcs()) {
846 if (pag.existsEdge(a.tail(), a.head())) {
847 pag.setMarkAt(a.tail(), a.head(), EdgeMark::Arrowhead);
848 pag.setMarkAt(a.head(), a.tail(), EdgeMark::Tail);
849 }
850 }
851 orientCollidersOnPAG_(pag, pag.toMixedGraph());
852
853 // Phase 5: orientation rules R1–R10 (fixed-point)
855
856 // Phase 6: collect bidirected edges (↔) as latent couples
857 _latentCouples_.clear();
858 for (const Edge& e: pag.edges()) {
859 if (pag.isBidirected(e.first(), e.second())) {
860 _latentCouples_.emplace_back(e.first(), e.second());
861 }
862 }
863
864 return pag;
865 }
MixedGraph learnSkeleton(MixedGraph graph) override
Phase 1: skeleton discovery via conditional independence tests.
void applyStructuralConstraints_(MixedGraph &graph)
Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural cons...
void orientCollidersOnPAG_(PAG &pag, const MixedGraph &topology)
Phase 2 / Phase 4: orient unshielded colliders directly on the PAG. topology is used for unshielded-t...
Definition FCI.cpp:102
void applyOrientationRules_(PAG &pag) const
Phase 5: fixed-point loop over all orientation rules R1–R10.
Definition FCI.cpp:797
void possibleDSepPhase_(PAG &pag)
Phase 3: prune PAG edges using possibleDSep conditioning sets.
Definition FCI.cpp:287

References gum::learning::ConstraintBasedLearning::_latentCouples_, gum::PAG::addEdge(), gum::NodeGraphPart::addNodeWithId(), applyOrientationRules_(), gum::learning::ConstraintBasedLearning::applyStructuralConstraints_(), gum::ArcGraphPart::arcs(), gum::Arrowhead, gum::Circle, gum::EdgeGraphPart::edges(), gum::EdgeGraphPart::existsEdge(), gum::PAG::isBidirected(), gum::learning::CIBasedLearning::learnSkeleton(), gum::NodeGraphPart::nodes(), orientCollidersOnPAG_(), possibleDSepPhase_(), gum::PAG::reorientAllWith(), gum::PAG::setMarkAt(), gum::Tail, and gum::PAG::toMixedGraph().

Referenced by ~FCI(), and learnMixedStructure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ learnPDAG()

PDAG gum::learning::ConstraintBasedLearning::learnPDAG ( MixedGraph graph)
inherited

learns the essential graph (CPDAG)

Definition at line 137 of file ConstraintBasedLearning.cpp.

137 {
138 return meekRules_.propagateToCPDAG(learnMixedStructure(graph));
139 }

References learnMixedStructure(), and meekRules_.

Here is the call graph for this function:

◆ learnSkeleton()

MixedGraph gum::learning::CIBasedLearning::learnSkeleton ( MixedGraph graph)
overridevirtualinherited

Phase 1: skeleton discovery via conditional independence tests.

Implements gum::learning::ConstraintBasedLearning.

Definition at line 126 of file CIBasedLearning.cpp.

126 {
127 graph = initGraph_(graph);
128 sepSet_.clear();
129
130 Size d = 0;
131 while (d <= maxCondSetSize_) {
132 std::vector< Edge > edges(graph.edges().begin(), graph.edges().end());
133
134 bool anyTested = false;
135 std::vector< Edge > toRemove;
136
137 for (const Edge& edge: edges) {
138 if (!graph.existsEdge(edge)) { continue; }
139
140 const NodeId X = edge.first();
141 const NodeId Y = edge.second();
142
143 [&]() {
144 if (d == 0) {
145 anyTested = true;
146 const double pval = test_->statistics(X, Y, _emptySet_).second;
147 if (pval <= alpha_) { return; }
148 if (stable_) {
149 toRemove.push_back(edge);
150 } else {
151 graph.eraseEdge(edge);
152 }
153 sepSet_.insert({X, Y}, {{}, pval});
154 sepSet_.insert({Y, X}, {{}, pval});
155 return;
156 }
157
158 bool exh_found = false;
159 std::set< NodeId > exh_union;
160 double exh_pval = 0.0;
161
162 for (int dir = 0; dir < 2; ++dir) {
163 const NodeId A = (dir == 0) ? X : Y;
164 const NodeId B = (dir == 0) ? Y : X;
165
166 std::vector< NodeId > adj;
167 for (NodeId nb: graph.neighbours(A)) {
168 if (nb != B) { adj.push_back(nb); }
169 }
170
171 if (static_cast< Size >(adj.size()) < d) { continue; }
172 anyTested = true;
173
174 std::vector< std::size_t > idx(d);
175 std::iota(idx.begin(), idx.end(), std::size_t(0));
176
177 for (;;) {
178 std::vector< NodeId > cond(d);
179 for (Size i = 0; i < d; ++i) {
180 cond[i] = adj[idx[i]];
181 }
182
183 const double pval = test_->statistics(A, B, cond).second;
184 if (pval > alpha_) {
185 if (!exhaustiveSepSet_) {
186 if (stable_) {
187 toRemove.push_back(edge);
188 } else {
189 graph.eraseEdge(edge);
190 }
191 sepSet_.insert({X, Y}, {cond, pval});
192 sepSet_.insert({Y, X}, {cond, pval});
193 return;
194 }
195 exh_found = true;
196 if (exh_pval == 0.0) { exh_pval = pval; }
197 for (const NodeId n: cond) {
198 exh_union.insert(n);
199 }
200 }
201
202 int i = static_cast< int >(d) - 1;
203 while (i >= 0 && idx[i] == adj.size() - d + static_cast< std::size_t >(i)) {
204 --i;
205 }
206 if (i < 0) { break; }
207 ++idx[i];
208 for (int j = i + 1; j < static_cast< int >(d); ++j) {
209 idx[j] = idx[j - 1] + 1;
210 }
211 }
212 }
213
214 if (exh_found) {
215 if (stable_) {
216 toRemove.push_back(edge);
217 } else {
218 graph.eraseEdge(edge);
219 }
220 const std::vector< NodeId > union_vec(exh_union.begin(), exh_union.end());
221 sepSet_.insert({X, Y}, {union_vec, exh_pval});
222 sepSet_.insert({Y, X}, {union_vec, exh_pval});
223 }
224 }();
225 }
226
227 if (stable_) {
228 for (const Edge& e: toRemove) {
229 if (graph.existsEdge(e)) { graph.eraseEdge(e); }
230 }
231 }
232
233 if (!anyTested) { break; }
234 ++d;
235 }
236
237 return graph;
238 }
MixedGraph initGraph_(const MixedGraph &template_graph)
Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural cons...
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74

References gum::learning::ConstraintBasedLearning::_emptySet_, alpha_, exhaustiveSepSet_, gum::learning::ConstraintBasedLearning::initGraph_(), maxCondSetSize_, sepSet_, stable_, and test_.

Referenced by ~CIBasedLearning(), gum::learning::PC::learnMixedStructure(), and gum::learning::FCI::learnPAG().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ maxIter()

INLINE Size gum::ApproximationScheme::maxIter ( ) const
overridevirtualinherited

Returns the criterion on number of iterations.

Returns
Returns the criterion on number of iterations.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 113 of file approximationScheme_inl.h.

113{ return max_iter_; }

References max_iter_.

◆ maxPathLength()

Size gum::learning::FCI::maxPathLength ( ) const

maximum path length for R4 discriminating-path search; Size(-1) = unlimited

Definition at line 84 of file FCI.cpp.

84{ return maxPathLength_; }

References maxPathLength_.

Referenced by ~FCI().

Here is the caller graph for this function:

◆ maxTime()

INLINE double gum::ApproximationScheme::maxTime ( ) const
overridevirtualinherited

Returns the timeout (in seconds).

Returns
Returns the timeout (in seconds).

Implements gum::IApproximationSchemeConfiguration.

Definition at line 134 of file approximationScheme_inl.h.

134{ return max_time_; }

References max_time_.

◆ messageApproximationScheme()

std::string gum::IApproximationSchemeConfiguration::messageApproximationScheme ( ) const
inherited

Returns the approximation scheme message.

Returns
Returns the approximation scheme message.

Definition at line 64 of file IApproximationSchemeConfiguration.cpp.

64 {
65 switch (stateApproximationScheme()) {
66 case ApproximationSchemeSTATE::Continue : return "in progress";
67
69 return std::format("stopped with epsilon={}", epsilon());
70
72 return std::format("stopped with rate={}", minEpsilonRate());
73
75 return std::format("stopped with max iteration={}", maxIter());
76
78 return std::format("stopped with timeout={}", maxTime());
79
80 case ApproximationSchemeSTATE::Stopped : return "stopped on request";
81
82 case ApproximationSchemeSTATE::Undefined : return "undefined state";
83 }
84 return {};
85 }
virtual double epsilon() const =0
Returns the value of epsilon.
virtual ApproximationSchemeSTATE stateApproximationScheme() const =0
Returns the approximation scheme state.
virtual double minEpsilonRate() const =0
Returns the value of the minimal epsilon rate.
virtual Size maxIter() const =0
Returns the criterion on number of iterations.
virtual double maxTime() const =0
Returns the timeout (in seconds).

References Continue, Epsilon, epsilon(), Limit, maxIter(), maxTime(), minEpsilonRate(), Rate, stateApproximationScheme(), Stopped, TimeLimit, and Undefined.

Referenced by gum::ApproximationScheme::continueApproximationScheme(), gum::credal::InferenceEngine< GUM_SCALAR >::getApproximationSchemeMsg(), and gum::credal::MultipleInferenceEngine< GUM_SCALAR, LazyPropagation< GUM_SCALAR > >::isEnabledMaxIter().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ minEpsilonRate()

INLINE double gum::ApproximationScheme::minEpsilonRate ( ) const
overridevirtualinherited

Returns the value of the minimal epsilon rate.

Returns
Returns the value of the minimal epsilon rate.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 93 of file approximationScheme_inl.h.

93{ return min_rate_eps_; }

References min_rate_eps_.

◆ nbrIterations()

INLINE Size gum::ApproximationScheme::nbrIterations ( ) const
overridevirtualinherited

Returns the number of iterations.

Returns
Returns the number of iterations.
Exceptions
OperationNotAllowedRaised if the scheme did not perform.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 170 of file approximationScheme_inl.h.

170 {
172 GUM_ERROR(OperationNotAllowed, "state of the approximation scheme is undefined")
173 }
174
175 return current_step_;
176 }

References current_step_, GUM_ERROR, stateApproximationScheme(), and gum::IApproximationSchemeConfiguration::Undefined.

Referenced by gum::GibbsBNdistance< GUM_SCALAR >::computeKL_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator=() [1/2]

FCI & gum::learning::FCI::operator= ( const FCI & from)

Definition at line 62 of file FCI.cpp.

62 {
63 if (this != &from) {
65 maxPathLength_ = from.maxPathLength_;
66 }
67 return *this;
68 }
CIBasedLearning & operator=(const CIBasedLearning &)

References FCI(), maxPathLength_, and gum::learning::CIBasedLearning::operator=().

Here is the call graph for this function:

◆ operator=() [2/2]

FCI & gum::learning::FCI::operator= ( FCI && from)
noexcept

Definition at line 70 of file FCI.cpp.

70 {
71 if (this != &from) {
72 CIBasedLearning::operator=(std::move(from));
73 maxPathLength_ = from.maxPathLength_;
74 }
75 return *this;
76 }

References FCI(), maxPathLength_, and gum::learning::CIBasedLearning::operator=().

Here is the call graph for this function:

◆ orientColliderArm_()

void gum::learning::CIBasedLearning::orientColliderArm_ ( MixedGraph & graph,
NodeId src,
NodeId dst )
protectedinherited

orient one arm (src → dst) of a collider; calls resolveOrientConflict_ on conflict

Definition at line 244 of file CIBasedLearning.cpp.

244 {
245 if (graph.existsEdge(src, dst)) {
246 if (isArcValid_(graph, src, dst) && !_existsDirectedPath_(graph, dst, src)) {
247 graph.eraseEdge(Edge(src, dst));
248 graph.addArc(src, dst);
249 GUM_SL_EMIT(src, dst, "Orient " << src << " -> " << dst, "V-structure collider");
250 } else {
251 resolveOrientConflict_(src, dst);
252 GUM_SL_EMIT(src,
253 dst,
254 "Conflict " << src << " -> " << dst,
255 "V-structure blocked by constraint");
256 }
257 } else if (graph.existsArc(dst, src)) {
258 resolveOrientConflict_(src, dst);
259 GUM_SL_EMIT(src, dst, "Conflict " << src << " -> " << dst, "V-structure conflict: latent?");
260 }
261 // existsArc(src, dst) → consistent, skip
262 }
virtual void resolveOrientConflict_(NodeId src, NodeId dst)
conflict hook: called when orientation cannot proceed (arc blocked or reversed). Default: push Arc(sr...
bool isArcValid_(const MixedGraph &graph, NodeId x, NodeId y)

References gum::learning::ConstraintBasedLearning::_existsDirectedPath_(), GUM_SL_EMIT, gum::learning::ConstraintBasedLearning::isArcValid_(), and resolveOrientConflict_().

Referenced by orientUnshieldedColliders_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ orientCollidersOnPAG_()

void gum::learning::FCI::orientCollidersOnPAG_ ( PAG & pag,
const MixedGraph & topology )
private

Phase 2 / Phase 4: orient unshielded colliders directly on the PAG. topology is used for unshielded-triple detection (adjacency queries only).

Definition at line 102 of file FCI.cpp.

102 {
103 const auto triples = unshieldedTriples_(topology);
104
105 const auto isCollider = [&](NodeId X, NodeId Y, NodeId Z) -> bool {
106 if (!sepSet_.exists({X, Y})) { return false; }
107 const SepSetEntry_& entry = sepSet_[{X, Y}];
108 return std::ranges::find(entry.cond, Z) == entry.cond.end();
109 };
110
112 for (const ThreePoints& tp: triples) {
113 const NodeId X = std::get< 0 >(tp);
114 const NodeId Y = std::get< 1 >(tp);
115 const NodeId Z = std::get< 2 >(tp);
116 if (!isCollider(X, Y, Z)) { continue; }
117 if (pag.existsEdge(X, Z) && !isForbiddenArc_(X, Z)) {
118 pag.setMarkAt(X, Z, EdgeMark::Arrowhead);
119 }
120 if (pag.existsEdge(Y, Z) && !isForbiddenArc_(Y, Z)) {
121 pag.setMarkAt(Y, Z, EdgeMark::Arrowhead);
122 }
123 }
124 } else {
125 struct Candidate {
126 NodeId X, Y, Z;
127 double pval;
128 };
129
130 std::vector< Candidate > candidates;
131 candidates.reserve(triples.size());
132
133 for (const ThreePoints& tp: triples) {
134 const NodeId X = std::get< 0 >(tp);
135 const NodeId Y = std::get< 1 >(tp);
136 const NodeId Z = std::get< 2 >(tp);
137 if (!isCollider(X, Y, Z)) { continue; }
138 candidates.push_back({.X = X, .Y = Y, .Z = Z, .pval = sepSet_[{X, Y}].pval});
139 }
140
141 std::ranges::sort(candidates,
142 [](const Candidate& a, const Candidate& b) { return a.pval > b.pval; });
143
144 for (const auto& [X, Y, Z, pval]: candidates) {
145 if (pag.existsEdge(X, Z) && !isForbiddenArc_(X, Z)) {
146 pag.setMarkAt(X, Z, EdgeMark::Arrowhead);
147 }
148 if (pag.existsEdge(Y, Z) && !isForbiddenArc_(Y, Z)) {
149 pag.setMarkAt(Y, Z, EdgeMark::Arrowhead);
150 }
151 }
152 }
153 }
@ Standard
process triples in natural traversal order
std::vector< ThreePoints > unshieldedTriples_(const MixedGraph &graph)
Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural cons...
std::tuple< NodeId, NodeId, NodeId > ThreePoints

References gum::Arrowhead, gum::learning::CIBasedLearning::SepSetEntry_::cond, gum::EdgeGraphPart::existsEdge(), gum::learning::ConstraintBasedLearning::isForbiddenArc_(), gum::learning::CIBasedLearning::sepSet_, gum::PAG::setMarkAt(), gum::learning::CIBasedLearning::Standard, gum::learning::CIBasedLearning::ucPriority_, and gum::learning::ConstraintBasedLearning::unshieldedTriples_().

Referenced by ~FCI(), and learnPAG().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ orientDoubleHeadedArcs_()

void gum::learning::ConstraintBasedLearning::orientDoubleHeadedArcs_ ( MixedGraph & mg)
protectedinherited

Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.

Definition at line 204 of file ConstraintBasedLearning.cpp.

204 {
205 gum::ArcSet L;
206 for (gum::NodeId x: mg.nodes())
207 for (NodeId y: mg.parents(x))
208 if (mg.parents(y).contains(x)) {
209 if (x > y) continue;
210 else L.insert(gum::Arc(x, y));
211 }
212
213 if (not L.empty()) {
214 while (true) {
215 bool withdrawFlag_L = false;
216 for (auto arc: ArcSet(L)) {
217 bool tail_head = _existsDirectedPath_(mg, arc.tail(), arc.head());
218 bool head_tail = _existsDirectedPath_(mg, arc.head(), arc.tail());
219 bool withdrawFlag_arc = false;
220
221 if (tail_head && !head_tail) {
222 mg.eraseArc(Arc(arc.head(), arc.tail()));
223 withdrawFlag_arc = true;
224 } else if (!tail_head && head_tail) {
225 mg.eraseArc(Arc(arc.tail(), arc.head()));
226 withdrawFlag_arc = true;
227 } else if (!tail_head && !head_tail) {
228 mg.eraseArc(Arc(arc.head(), arc.tail()));
229 withdrawFlag_arc = true;
230 }
231
232 if (withdrawFlag_arc) {
233 L.erase(arc);
234 withdrawFlag_L = true;
235 }
236 }
237 if (L.empty()) break;
238
239 // no arc was processed this pass — break cycle by erasing one arc arbitrarily
240 if (!withdrawFlag_L) {
241 auto arc = *L.begin();
242 mg.eraseArc(Arc(arc.head(), arc.tail()));
243 mg.eraseArc(Arc(arc.tail(), arc.head()));
244 L.erase(arc);
245 }
246 }
247 }
248 }
bool empty() const noexcept
Indicates whether the set is the empty set.
Definition set_tpl.h:613
iterator begin() const
The usual unsafe begin iterator to parse the set.
Definition set_tpl.h:409
void insert(const Key &k)
Inserts a new element into the set.
Definition set_tpl.h:510
void erase(const Key &k)
Erases an element from the set.
Definition set_tpl.h:553
Set< Arc > ArcSet
Some typdefs and define for shortcuts ...

References _existsDirectedPath_(), gum::Set< Key >::begin(), gum::Set< Key >::contains(), gum::Set< Key >::empty(), gum::Set< Key >::erase(), gum::ArcGraphPart::eraseArc(), gum::Set< Key >::insert(), gum::NodeGraphPart::nodes(), and gum::ArcGraphPart::parents().

Referenced by gum::learning::FCI::learnMixedStructure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ orientUnshieldedColliders_()

MixedGraph gum::learning::CIBasedLearning::orientUnshieldedColliders_ ( MixedGraph graph)
protectedinherited

orient unshielded colliders in graph and return the updated graph

Definition at line 268 of file CIBasedLearning.cpp.

268 {
269 _latentCouples_.clear();
270
271 const auto triples = unshieldedTriples_(graph);
272
273 const auto isCollider = [&](NodeId X, NodeId Y, NodeId Z) -> bool {
274 if (!sepSet_.exists({X, Y})) { return false; }
275 const SepSetEntry_& entry = sepSet_[{X, Y}];
276 return std::find(entry.cond.begin(), entry.cond.end(), Z) == entry.cond.end();
277 };
278
280 for (const ThreePoints& tp: triples) {
281 const NodeId X = std::get< 0 >(tp);
282 const NodeId Y = std::get< 1 >(tp);
283 const NodeId Z = std::get< 2 >(tp);
284 if (!isCollider(X, Y, Z)) { continue; }
285 orientColliderArm_(graph, X, Z);
286 orientColliderArm_(graph, Y, Z);
287 }
288 } else {
289 struct Candidate {
290 NodeId X, Y, Z;
291 double pval;
292 };
293
294 std::vector< Candidate > candidates;
295 candidates.reserve(triples.size());
296
297 for (const ThreePoints& tp: triples) {
298 const NodeId X = std::get< 0 >(tp);
299 const NodeId Y = std::get< 1 >(tp);
300 const NodeId Z = std::get< 2 >(tp);
301 if (!isCollider(X, Y, Z)) { continue; }
302 candidates.push_back({X, Y, Z, sepSet_[{X, Y}].pval});
303 }
304
305 std::sort(candidates.begin(), candidates.end(), [](const Candidate& a, const Candidate& b) {
306 return a.pval > b.pval;
307 });
308
309 for (const auto& [X, Y, Z, pval]: candidates) {
310 orientColliderArm_(graph, X, Z);
311 orientColliderArm_(graph, Y, Z);
312 }
313 }
314
315 return graph;
316 }
void orientColliderArm_(MixedGraph &graph, NodeId src, NodeId dst)
orient one arm (src → dst) of a collider; calls resolveOrientConflict_ on conflict

References gum::learning::ConstraintBasedLearning::_latentCouples_, gum::learning::CIBasedLearning::SepSetEntry_::cond, orientColliderArm_(), sepSet_, Standard, ucPriority_, and gum::learning::ConstraintBasedLearning::unshieldedTriples_().

Referenced by gum::learning::PC::learnMixedStructure().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ periodSize()

INLINE Size gum::ApproximationScheme::periodSize ( ) const
overridevirtualinherited

Returns the period size.

Returns
Returns the period size.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 156 of file approximationScheme_inl.h.

156{ return period_size_; }
Size period_size_
Checking criteria frequency.

References period_size_.

◆ possibleDSep()

std::vector< NodeId > gum::learning::FCI::possibleDSep ( const PAG & pag,
NodeId x,
NodeId y ) const

learnSkeleton() inherited from CIBasedLearning

return all nodes on possible-d-sep paths from x toward y (excl. x and y). Public accessor for testing and introspection.

Definition at line 86 of file FCI.cpp.

86 {
87 return computePossibleDSep_(pag, x, y);
88 }
std::vector< NodeId > computePossibleDSep_(const PAG &pag, NodeId x, NodeId y) const
Phase 3: return all nodes on possible-d-sep paths from x toward y (excl. x, y).
Definition FCI.cpp:248

References computePossibleDSep_().

Referenced by ~FCI().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ possibleDSepPhase_()

void gum::learning::FCI::possibleDSepPhase_ ( PAG & pag)
private

Phase 3: prune PAG edges using possibleDSep conditioning sets.

Definition at line 287 of file FCI.cpp.

287 {
288 // snapshot edges to avoid invalidation during removal
289 const std::vector< Edge > edgeSnap(pag.edges().begin(), pag.edges().end());
290
291 const auto tryRemove = [&](NodeId X, NodeId Y, const std::vector< NodeId >& dsep) {
292 const Size maxK = (maxCondSetSize_ == Size(-1))
293 ? static_cast< Size >(dsep.size())
294 : std::min(maxCondSetSize_, static_cast< Size >(dsep.size()));
295
296 // FIX #4: start at k=2; sizes 0 and 1 were already exhaustively tested
297 // in Phase 1 (FAS skeleton discovery).
298 for (Size k = 2; k <= maxK; ++k) {
299 if (dsep.size() < k) { break; }
300
301 std::vector< std::size_t > idx(k);
302 std::iota(idx.begin(), idx.end(), std::size_t(0));
303
304 for (;;) {
305 std::vector< NodeId > cond(k);
306 for (Size i = 0; i < k; ++i) {
307 cond[i] = dsep[idx[i]];
308 }
309
310 const double pval = test_->statistics(X, Y, cond).second;
311 if (pval > alpha_) {
312 pag.eraseEdge(Edge(X, Y));
313 sepSet_.set({X, Y}, SepSetEntry_{.cond = cond, .pval = pval});
314 sepSet_.set({Y, X}, SepSetEntry_{.cond = cond, .pval = pval});
315 return true;
316 }
317
318 if (k == 0) { break; }
319 int i = static_cast< int >(k) - 1;
320 while (i >= 0
321 && idx[static_cast< std::size_t >(i)]
322 == dsep.size() - k + static_cast< std::size_t >(i)) {
323 --i;
324 }
325 if (i < 0) { break; }
326 ++idx[static_cast< std::size_t >(i)];
327 for (int j = i + 1; j < static_cast< int >(k); ++j) {
328 idx[static_cast< std::size_t >(j)] = idx[static_cast< std::size_t >(j - 1)] + 1;
329 }
330 }
331 }
332 return false;
333 };
334
335 for (const Edge& edge: edgeSnap) {
336 if (!pag.existsEdge(edge)) { continue; }
337 const NodeId X = edge.first();
338 const NodeId Y = edge.second();
339
340 const auto dsepXY = computePossibleDSep_(pag, X, Y);
341 if (tryRemove(X, Y, dsepXY)) { continue; }
342
343 if (!pag.existsEdge(edge)) { continue; }
344 const auto dsepYX = computePossibleDSep_(pag, Y, X);
345 tryRemove(X, Y, dsepYX);
346 }
347 }

References gum::learning::CIBasedLearning::alpha_, gum::Set< Key >::begin(), computePossibleDSep_(), gum::EdgeGraphPart::edges(), gum::Set< Key >::end(), gum::PAG::eraseEdge(), gum::EdgeGraphPart::existsEdge(), gum::learning::CIBasedLearning::maxCondSetSize_, gum::learning::CIBasedLearning::sepSet_, and gum::learning::CIBasedLearning::test_.

Referenced by ~FCI(), and learnPAG().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remainingBurnIn()

INLINE Size gum::ApproximationScheme::remainingBurnIn ( ) const
inherited

Returns the remaining burn in.

Returns
Returns the remaining burn in.

Definition at line 213 of file approximationScheme_inl.h.

213 {
214 if (burn_in_ > current_step_) {
215 return burn_in_ - current_step_;
216 } else {
217 return 0;
218 }
219 }
Size burn_in_
Number of iterations before checking stopping criteria.

References burn_in_, and current_step_.

◆ resolveOrientConflict_()

void gum::learning::FCI::resolveOrientConflict_ ( NodeId src,
NodeId dst )
overrideprotectedvirtual

conflict hook override: FCI leaves circle marks — orientation conflicts are not recorded as latent couples here (only final ↔ edges in Phase 6 are)

Reimplemented from gum::learning::CIBasedLearning.

Definition at line 94 of file FCI.cpp.

94 {
95 // no-op: circle marks remain; only final ↔ edges (Phase 6) become _latentCouples_
96 }

Referenced by ~FCI().

Here is the caller graph for this function:

◆ ruleR10_()

bool gum::learning::FCI::ruleR10_ ( PAG & pag) const
private

away from ancestor via two semi-directed paths

Definition at line 744 of file FCI.cpp.

744 {
745 bool changed = false;
746 for (const NodeId c: pag.nodes()) {
747 // all nodes with arrowhead into C
748 std::vector< NodeId > into_c;
749 for (const NodeId n: pag.neighbours(c)) {
750 if (pag.isArrowhead(n, c)) { into_c.push_back(n); }
751 }
752 if (into_c.size() < 2) { continue; }
753
754 for (const NodeId a: into_c) {
755 if (!pag.isCircle(c, a)) { continue; } // A o→ C
756 // possible children of A (not C)
757 std::vector< NodeId > a_children;
758 for (const NodeId x: pag.neighbours(a)) {
759 if (x == c) { continue; }
760 if (!pag.isArrowhead(x, a)) { a_children.push_back(x); }
761 }
762 if (a_children.size() < 2) { continue; }
763
764 bool oriented = false;
765 for (std::size_t i = 0; i < into_c.size() && !oriented; ++i) {
766 for (std::size_t j = i + 1; j < into_c.size() && !oriented; ++j) {
767 const NodeId bd = into_c[i];
768 const NodeId dd = into_c[j];
769 if (!pag.isTail(c, bd)) { continue; } // B→C
770 if (!pag.isTail(c, dd)) { continue; } // D→C
771 for (std::size_t m = 0; m < a_children.size() && !oriented; ++m) {
772 for (std::size_t n2 = m + 1; n2 < a_children.size() && !oriented; ++n2) {
773 const NodeId ch1 = a_children[m];
774 const NodeId ch2 = a_children[n2];
775 if (pag.existsEdge(ch1, ch2)) { continue; }
776 // FIX #6: check both (ch1→bd, ch2→dd) and (ch1→dd, ch2→bd).
777 // Zhang 2008 R10 requires one path to B and one to D from two
778 // non-adjacent children; either assignment of children to targets
779 // is valid.
780 const bool direct = existsSemiDirectedPath_(pag, ch1, bd)
781 && existsSemiDirectedPath_(pag, ch2, dd);
782 const bool crossed = existsSemiDirectedPath_(pag, ch1, dd)
783 && existsSemiDirectedPath_(pag, ch2, bd);
784 if (!direct && !crossed) { continue; }
785 pag.setMarkAt(c, a, EdgeMark::Tail);
786 changed = true;
787 oriented = true;
788 }
789 }
790 }
791 }
792 }
793 }
794 return changed;
795 }

References gum::EdgeGraphPart::existsEdge(), gum::PAG::isArrowhead(), gum::PAG::isCircle(), gum::PAG::isTail(), gum::EdgeGraphPart::neighbours(), gum::NodeGraphPart::nodes(), gum::PAG::setMarkAt(), and gum::Tail.

Referenced by ~FCI(), and applyOrientationRules_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ruleR1_()

bool gum::learning::FCI::ruleR1_ ( PAG & pag) const
private

away from collider

Definition at line 354 of file FCI.cpp.

354 {
355 bool changed = false;
356 for (const NodeId b: pag.nodes()) {
357 for (const NodeId a: pag.neighbours(b)) {
358 if (!pag.isArrowhead(a, b)) { continue; }
359 for (const NodeId c: pag.neighbours(b)) {
360 if (c == a) { continue; }
361 if (!pag.isCircle(c, b)) { continue; }
362 if (pag.existsEdge(a, c)) { continue; }
363 if (isForbiddenArc_(b, c)) { continue; }
364 // FIX #1: do not overwrite an existing Tail at C (from B) with Arrowhead.
365 // marks_[Arc(B,C)] == Tail means B *— C is already established;
366 // upgrading it to B *→ C would contradict that orientation.
367 if (pag.isTail(b, c)) { continue; }
368 pag.setMarkAt(c, b, EdgeMark::Tail);
369 pag.setMarkAt(b, c, EdgeMark::Arrowhead);
370 changed = true;
371 }
372 }
373 }
374 return changed;
375 }

References gum::Arrowhead, gum::EdgeGraphPart::existsEdge(), gum::PAG::isArrowhead(), gum::PAG::isCircle(), gum::learning::ConstraintBasedLearning::isForbiddenArc_(), gum::PAG::isTail(), gum::EdgeGraphPart::neighbours(), gum::NodeGraphPart::nodes(), gum::PAG::setMarkAt(), and gum::Tail.

Referenced by ~FCI(), and applyOrientationRules_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ruleR2_()

bool gum::learning::FCI::ruleR2_ ( PAG & pag) const
private

away from cycle

Definition at line 378 of file FCI.cpp.

378 {
379 bool changed = false;
380 for (const NodeId b: pag.nodes()) {
381 for (const NodeId a: pag.neighbours(b)) {
382 for (const NodeId c: pag.neighbours(b)) {
383 if (a == c) { continue; }
384 if (!pag.existsEdge(a, c)) { continue; }
385 if (!pag.isCircle(a, c)) { continue; } // circle at c from a
386 if (!pag.isArrowhead(a, b)) { continue; } // a *→ b
387 if (!pag.isArrowhead(b, c)) { continue; } // b *→ c
388 if (!pag.isTail(b, a) && !pag.isTail(c, b)) { continue; }
389 if (isForbiddenArc_(a, c)) { continue; }
390 // FIX #1 (defensive): isCircle(a,c) already ensures the mark at C
391 // from A is Circle, so isTail cannot be true here. Added for symmetry
392 // with R1 and to make the guard explicit.
393 if (pag.isTail(a, c)) { continue; }
394 pag.setMarkAt(a, c, EdgeMark::Arrowhead);
395 changed = true;
396 }
397 }
398 }
399 return changed;
400 }

References gum::Arrowhead, gum::EdgeGraphPart::existsEdge(), gum::PAG::isArrowhead(), gum::PAG::isCircle(), gum::learning::ConstraintBasedLearning::isForbiddenArc_(), gum::PAG::isTail(), gum::EdgeGraphPart::neighbours(), gum::NodeGraphPart::nodes(), and gum::PAG::setMarkAt().

Referenced by ~FCI(), and applyOrientationRules_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ruleR3_()

bool gum::learning::FCI::ruleR3_ ( PAG & pag) const
private

double triangle

Definition at line 405 of file FCI.cpp.

405 {
406 bool changed = false;
407 for (const NodeId b: pag.nodes()) {
408 std::vector< NodeId > into_arrows, into_circles;
409 for (const NodeId n: pag.neighbours(b)) {
410 if (pag.isArrowhead(n, b)) { into_arrows.push_back(n); }
411 if (pag.isCircle(n, b)) { into_circles.push_back(n); }
412 }
413 if (into_arrows.size() < 2) { continue; }
414
415 for (const NodeId d: into_circles) {
416 for (std::size_t i = 0; i < into_arrows.size(); ++i) {
417 for (std::size_t j = i + 1; j < into_arrows.size(); ++j) {
418 const NodeId a = into_arrows[i];
419 const NodeId c = into_arrows[j];
420 if (pag.existsEdge(a, c)) { continue; } // A, C not adjacent
421 if (!pag.existsEdge(a, d)) { continue; }
422 if (!pag.existsEdge(c, d)) { continue; }
423 if (!pag.isCircle(a, d)) { continue; } // circle at d from a
424 if (!pag.isCircle(c, d)) { continue; } // circle at d from c
425 // D is non-collider on A-D-C: D ∈ sepSet(A,C)
426 bool nonCollider = false;
427 for (const auto& key: {std::make_pair(a, c), std::make_pair(c, a)}) {
428 if (sepSet_.exists(key)) {
429 const auto& cond = sepSet_[key].cond;
430 if (std::ranges::find(cond, d) != cond.end()) {
431 nonCollider = true;
432 break;
433 }
434 }
435 }
436 if (!nonCollider) { continue; }
437 pag.setMarkAt(d, b, EdgeMark::Arrowhead);
438 changed = true;
439 }
440 }
441 }
442 }
443 return changed;
444 }

References gum::Arrowhead, gum::EdgeGraphPart::existsEdge(), gum::PAG::isArrowhead(), gum::PAG::isCircle(), gum::EdgeGraphPart::neighbours(), gum::NodeGraphPart::nodes(), gum::learning::CIBasedLearning::sepSet_, and gum::PAG::setMarkAt().

Referenced by ~FCI(), and applyOrientationRules_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ruleR4_()

bool gum::learning::FCI::ruleR4_ ( PAG & pag) const
private

discriminating path (uses CI test)

Definition at line 595 of file FCI.cpp.

595 {
596 bool changed = false;
597
598 for (const NodeId b: pag.nodes()) {
599 // possA: nodes A where B *→ A
600 std::vector< NodeId > poss_a;
601 for (const NodeId a: pag.neighbours(b)) {
602 if (pag.isArrowhead(b, a)) { poss_a.push_back(a); }
603 }
604 // possC: nodes C where circle at B from C, AND B *→ C
605 std::vector< NodeId > poss_c;
606 for (const NodeId c: pag.neighbours(b)) {
607 if (pag.isCircle(c, b) && pag.isArrowhead(b, c)) { poss_c.push_back(c); }
608 }
609
610 for (const NodeId a: poss_a) {
611 for (const NodeId c: poss_c) {
612 if (a == c) { continue; }
613 if (!pag.existsEdge(a, c)) { continue; }
614 if (!pag.isArrowhead(a, c) || !pag.isTail(c, a)) { continue; } // A→C (parent)
615
616 // BFS backward from A to find discriminating path D…A,B,C
617 HashTable< NodeId, NodeId > previous;
618 previous.insert(a, b);
619
620 // parents of C: nodes with directed edge into C
621 std::set< NodeId > c_parents;
622 for (const NodeId n: pag.neighbours(c)) {
623 if (pag.isArrowhead(n, c) && pag.isTail(c, n)) { c_parents.insert(n); }
624 }
625
626 std::queue< NodeId > q;
627 std::set< NodeId > visited{a, b};
628 q.push(a);
629
630 // FIX #2: track BFS depth to respect maxPathLength_.
631 // cur_lvl_size counts nodes remaining at the current BFS level;
632 // nxt_lvl_size accumulates nodes pushed for the next level.
633 // distance is incremented each time we exhaust the current level.
634 int distance = 0;
635 Size cur_lvl_size = 1; // node_a is the sole node at level 0
636 Size nxt_lvl_size = 0;
637
638 bool found = false;
639 while (!q.empty() && !found) {
640 const NodeId t = q.front();
641 q.pop();
642
643 const NodeId prev_t = previous[t];
644
645 // nodes D with arrowhead INTO t
646 for (const NodeId d: pag.neighbours(t)) {
647 if (visited.count(d) > 0) { continue; }
648 if (!pag.isArrowhead(d, t)) { continue; }
649 // t must be def collider on (d, t, prev_t)
650 if (!pag.isArrowhead(prev_t, t)) { continue; }
651
652 previous.set(d, t);
653
654 if (!pag.existsEdge(d, c) && d != c) {
655 // found discriminating path
656 if (doDdpOrientation_(pag, d, a, b, c, previous)) {
657 changed = true;
658 found = true;
659 break;
660 }
661 }
662 if (c_parents.count(d) > 0) {
663 q.push(d);
664 visited.insert(d);
665 ++nxt_lvl_size;
666 }
667 }
668
669 if (!found) {
670 --cur_lvl_size;
671 if (cur_lvl_size == 0) {
672 ++distance;
673 if (maxPathLength_ != Size(-1) && static_cast< Size >(distance) > maxPathLength_) {
674 break;
675 }
676 cur_lvl_size = nxt_lvl_size;
677 nxt_lvl_size = 0;
678 }
679 }
680 }
681 }
682 }
683 }
684 return changed;
685 }
bool doDdpOrientation_(PAG &pag, NodeId d, NodeId a, NodeId b, NodeId c, const HashTable< NodeId, NodeId > &previous) const
R4 helper: orient B,C in a detected discriminating path D..A,B,C.
Definition FCI.cpp:539

References doDdpOrientation_(), gum::EdgeGraphPart::existsEdge(), gum::HashTable< Key, Val >::insert(), gum::PAG::isArrowhead(), gum::PAG::isCircle(), gum::PAG::isTail(), maxPathLength_, gum::EdgeGraphPart::neighbours(), gum::NodeGraphPart::nodes(), and gum::HashTable< Key, Val >::set().

Referenced by ~FCI(), and applyOrientationRules_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ruleR5_()

bool gum::learning::FCI::ruleR5_ ( PAG & pag) const
private

uncovered circle path → undirected

Definition at line 449 of file FCI.cpp.

449 {
450 bool changed = false;
451 for (const NodeId b: pag.nodes()) {
452 for (const NodeId a: pag.neighbours(b)) {
453 if (!pag.isCircle(a, b) || !pag.isCircle(b, a)) { continue; }
454 for (const NodeId c: pag.neighbours(a)) {
455 if (c == b) { continue; }
456 if (pag.existsEdge(b, c)) { continue; } // B not adj C
457 if (!pag.isCircle(a, c) || !pag.isCircle(c, a)) { continue; }
458 for (const NodeId d: pag.neighbours(b)) {
459 if (d == a || d == c) { continue; }
460 if (pag.existsEdge(a, d)) { continue; } // A not adj D
461 if (!pag.isCircle(b, d) || !pag.isCircle(d, b)) { continue; }
462 const std::vector< NodeId > excludes{a, b};
463 std::vector< std::vector< NodeId > > paths;
464 std::vector< NodeId > path{c};
465 std::set< NodeId > visited{c};
466 findUncoveredCirclePaths_(pag, d, path, visited, excludes, paths);
467 for (const auto& p: paths) {
468 changed = true;
469 pag.setMarkAt(b, a, EdgeMark::Tail);
470 pag.setMarkAt(a, b, EdgeMark::Tail);
471 pag.setMarkAt(c, a, EdgeMark::Tail);
472 pag.setMarkAt(a, c, EdgeMark::Tail);
473 pag.setMarkAt(b, p.back(), EdgeMark::Tail);
474 pag.setMarkAt(p.back(), b, EdgeMark::Tail);
475 for (std::size_t k = 0; k + 1 < p.size(); ++k) {
476 pag.setMarkAt(p[k + 1], p[k], EdgeMark::Tail);
477 pag.setMarkAt(p[k], p[k + 1], EdgeMark::Tail);
478 }
479 }
480 }
481 }
482 }
483 }
484 return changed;
485 }

References gum::EdgeGraphPart::existsEdge(), gum::PAG::isCircle(), gum::EdgeGraphPart::neighbours(), gum::NodeGraphPart::nodes(), gum::PAG::setMarkAt(), and gum::Tail.

Referenced by ~FCI(), and applyOrientationRules_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ruleR6_()

bool gum::learning::FCI::ruleR6_ ( PAG & pag) const
private

tail propagation from undirected edge

Definition at line 489 of file FCI.cpp.

489 {
490 bool changed = false;
491 for (const NodeId b: pag.nodes()) {
492 bool has_undirected = false;
493 for (const NodeId a: pag.neighbours(b)) {
494 if (pag.isTail(a, b) && pag.isTail(b, a)) {
495 has_undirected = true;
496 break;
497 }
498 }
499 if (!has_undirected) { continue; }
500 for (const NodeId c: pag.neighbours(b)) {
501 if (pag.isCircle(c, b)) {
502 pag.setMarkAt(c, b, EdgeMark::Tail);
503 changed = true;
504 }
505 }
506 }
507 return changed;
508 }

References gum::PAG::isCircle(), gum::PAG::isTail(), gum::EdgeGraphPart::neighbours(), gum::NodeGraphPart::nodes(), gum::PAG::setMarkAt(), and gum::Tail.

Referenced by ~FCI(), and applyOrientationRules_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ruleR7_()

bool gum::learning::FCI::ruleR7_ ( PAG & pag) const
private

tail propagation from A-oB

Definition at line 512 of file FCI.cpp.

512 {
513 bool changed = false;
514 for (const NodeId b: pag.nodes()) {
515 std::vector< NodeId > a_list;
516 for (const NodeId a: pag.neighbours(b)) {
517 if (pag.isCircle(a, b) && pag.isTail(b, a)) { a_list.push_back(a); }
518 }
519 if (a_list.empty()) { continue; }
520 for (const NodeId c: pag.neighbours(b)) {
521 if (!pag.isCircle(c, b)) { continue; }
522 for (const NodeId a: a_list) {
523 if (a == c) { continue; }
524 if (!pag.existsEdge(a, c)) {
525 pag.setMarkAt(c, b, EdgeMark::Tail);
526 changed = true;
527 break;
528 }
529 }
530 }
531 }
532 return changed;
533 }

References gum::EdgeGraphPart::existsEdge(), gum::PAG::isCircle(), gum::PAG::isTail(), gum::EdgeGraphPart::neighbours(), gum::NodeGraphPart::nodes(), gum::PAG::setMarkAt(), and gum::Tail.

Referenced by ~FCI(), and applyOrientationRules_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ruleR8_()

bool gum::learning::FCI::ruleR8_ ( PAG & pag) const
private

away from ancestor (graph only)

Definition at line 693 of file FCI.cpp.

693 {
694 bool changed = false;
695 for (const NodeId b: pag.nodes()) {
696 for (const NodeId a: pag.neighbours(b)) {
697 for (const NodeId c: pag.neighbours(b)) {
698 if (a == c) { continue; }
699 if (!pag.existsEdge(a, c)) { continue; }
700 if (!pag.isArrowhead(a, c)) { continue; } // A *→ C
701 if (!pag.isCircle(c, a)) { continue; } // circle at A from C
702 if (!pag.isArrowhead(b, c)) { continue; } // B *→ C
703 if (!pag.isTail(c, b)) { continue; } // Tail at B from C (B→C directed)
704 const bool case1 = pag.isArrowhead(a, b) && pag.isTail(b, a); // A→B
705 const bool case2 = pag.isCircle(a, b) && pag.isTail(b, a); // A-oB
706 if (!case1 && !case2) { continue; }
707 // FIX #1 (defensive): isCircle(c,a) already ensures this is not Arrowhead,
708 // but guard explicitly for clarity.
709 if (pag.isArrowhead(c, a)) { continue; }
710 pag.setMarkAt(c, a, EdgeMark::Tail); // A→C: tail at A from C
711 changed = true;
712 }
713 }
714 }
715 return changed;
716 }

References gum::EdgeGraphPart::existsEdge(), gum::PAG::isArrowhead(), gum::PAG::isCircle(), gum::PAG::isTail(), gum::EdgeGraphPart::neighbours(), gum::NodeGraphPart::nodes(), gum::PAG::setMarkAt(), and gum::Tail.

Referenced by ~FCI(), and applyOrientationRules_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ruleR9_()

bool gum::learning::FCI::ruleR9_ ( PAG & pag) const
private

away from ancestor via uncovered pd-path

Definition at line 719 of file FCI.cpp.

719 {
720 bool changed = false;
721 for (const NodeId c: pag.nodes()) {
722 for (const NodeId a: pag.neighbours(c)) {
723 if (!pag.isArrowhead(a, c)) { continue; } // A *→ C
724 if (!pag.isCircle(c, a)) { continue; } // circle at A from C (A o→ C)
725 bool oriented = false;
726 for (const NodeId b: pag.neighbours(a)) {
727 if (b == c) { continue; }
728 if (pag.existsEdge(b, c)) { continue; } // B not adjacent C
729 if (pag.isArrowhead(b, a)) { continue; } // B must be possible child of A
730 if (existsUncoveredPdPath_(pag, a, b, c)) {
731 pag.setMarkAt(c, a, EdgeMark::Tail);
732 changed = true;
733 oriented = true;
734 break;
735 }
736 }
737 if (oriented) { continue; }
738 }
739 }
740 return changed;
741 }

References gum::EdgeGraphPart::existsEdge(), gum::PAG::isArrowhead(), gum::PAG::isCircle(), gum::EdgeGraphPart::neighbours(), gum::NodeGraphPart::nodes(), gum::PAG::setMarkAt(), and gum::Tail.

Referenced by ~FCI(), and applyOrientationRules_().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setAlpha()

void gum::learning::CIBasedLearning::setAlpha ( double alpha)
inherited

maximum conditioning set size; Size(-1) = unlimited (default)

Definition at line 106 of file CIBasedLearning.cpp.

106{ alpha_ = alpha; }
double alpha() const
maximum conditioning set size; Size(-1) = unlimited (default)

References alpha(), and alpha_.

Referenced by ~CIBasedLearning().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setEpsilon()

INLINE void gum::ApproximationScheme::setEpsilon ( double eps)
overridevirtualinherited

Given that we approximate f(t), stopping criterion on |f(t+1)-f(t)|.

If the criterion was disabled it will be enabled.

Parameters
epsThe new epsilon value.
Exceptions
OutOfBoundsRaised if eps < 0.

Implements gum::IApproximationSchemeConfiguration.

Reimplemented in gum::learning::EMApproximationScheme.

Definition at line 64 of file approximationScheme_inl.h.

64 {
65 if (eps < 0.) { GUM_ERROR(OutOfBounds, "eps should be >=0") }
66
67 eps_ = eps;
68 enabled_eps_ = true;
69 }

References enabled_eps_, eps_, and GUM_ERROR.

Referenced by gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), gum::GibbsSampling< GUM_SCALAR >::GibbsSampling(), gum::learning::GreedyHillClimbing::GreedyHillClimbing(), gum::learning::GreedyThickThinning::GreedyThickThinning(), gum::SamplingInference< GUM_SCALAR >::SamplingInference(), and gum::learning::EMApproximationScheme::setEpsilon().

Here is the caller graph for this function:

◆ setExhaustiveSepSet()

void gum::learning::CIBasedLearning::setExhaustiveSepSet ( bool exhaustive)
inherited

exhaustive sepset mode: accumulate union of all separating sets found at each depth, rather than stopping at the first (default: false)

Definition at line 114 of file CIBasedLearning.cpp.

114{ exhaustiveSepSet_ = exhaustive; }

References exhaustiveSepSet_.

Referenced by ~CIBasedLearning().

Here is the caller graph for this function:

◆ setForbiddenGraph()

void gum::learning::ConstraintBasedLearning::setForbiddenGraph ( const gum::DiGraph & forbidGraph)
inherited

Definition at line 118 of file ConstraintBasedLearning.cpp.

118 {
119 _forbiddenGraph_ = forbidGraph;
120 }

References _forbiddenGraph_.

◆ setIndependenceTest()

void gum::learning::CIBasedLearning::setIndependenceTest ( IndependenceTest & test)
inherited

inject independence test (non-owning: caller manages lifetime)

Definition at line 104 of file CIBasedLearning.cpp.

104{ test_ = &test; }

References test_.

Referenced by ~CIBasedLearning().

Here is the caller graph for this function:

◆ setMandatoryGraph()

void gum::learning::ConstraintBasedLearning::setMandatoryGraph ( const gum::DAG & mandaGraph)
inherited

Definition at line 114 of file ConstraintBasedLearning.cpp.

114 {
115 _mandatoryGraph_ = mandaGraph;
116 }

References _mandatoryGraph_.

◆ setMaxCondSetSize()

void gum::learning::CIBasedLearning::setMaxCondSetSize ( Size max_k)
inherited

maximum conditioning set size; Size(-1) = unlimited (default)

Definition at line 110 of file CIBasedLearning.cpp.

110{ maxCondSetSize_ = max_k; }

References maxCondSetSize_.

Referenced by ~CIBasedLearning().

Here is the caller graph for this function:

◆ setMaxIndegree()

void gum::learning::ConstraintBasedLearning::setMaxIndegree ( gum::Size n)
inherited

Definition at line 122 of file ConstraintBasedLearning.cpp.

122{ _maxIndegree_ = n; }

References _maxIndegree_.

◆ setMaxIter()

INLINE void gum::ApproximationScheme::setMaxIter ( Size max)
overridevirtualinherited

Stopping criterion on number of iterations.

If the criterion was disabled it will be enabled.

Parameters
maxThe maximum number of iterations.
Exceptions
OutOfBoundsRaised if max <= 1.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 106 of file approximationScheme_inl.h.

106 {
107 if (max < 1) { GUM_ERROR(OutOfBounds, "max should be >=1") }
108 max_iter_ = max;
109 enabled_max_iter_ = true;
110 }

References enabled_max_iter_, GUM_ERROR, and max_iter_.

Referenced by gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), and gum::SamplingInference< GUM_SCALAR >::SamplingInference().

Here is the caller graph for this function:

◆ setMaxPathLength()

void gum::learning::FCI::setMaxPathLength ( Size maxLen)

maximum path length for R4 discriminating-path search; Size(-1) = unlimited

Definition at line 82 of file FCI.cpp.

82{ maxPathLength_ = maxLen; }

References maxPathLength_.

Referenced by ~FCI().

Here is the caller graph for this function:

◆ setMaxTime()

INLINE void gum::ApproximationScheme::setMaxTime ( double timeout)
overridevirtualinherited

Stopping criterion on timeout.

If the criterion was disabled it will be enabled.

Parameters
timeoutThe timeout value in seconds.
Exceptions
OutOfBoundsRaised if timeout <= 0.0.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 127 of file approximationScheme_inl.h.

127 {
128 if (timeout <= 0.) { GUM_ERROR(OutOfBounds, "timeout should be >0.") }
129 max_time_ = timeout;
130 enabled_max_time_ = true;
131 }

References enabled_max_time_, GUM_ERROR, and max_time_.

Referenced by gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), and gum::SamplingInference< GUM_SCALAR >::SamplingInference().

Here is the caller graph for this function:

◆ setMinEpsilonRate()

INLINE void gum::ApproximationScheme::setMinEpsilonRate ( double rate)
overridevirtualinherited

Given that we approximate f(t), stopping criterion on d/dt(|f(t+1)-f(t)|).

If the criterion was disabled it will be enabled

Parameters
rateThe minimal epsilon rate.
Exceptions
OutOfBoundsif rate<0

Implements gum::IApproximationSchemeConfiguration.

Reimplemented in gum::learning::EMApproximationScheme.

Definition at line 85 of file approximationScheme_inl.h.

85 {
86 if (rate < 0) { GUM_ERROR(OutOfBounds, "rate should be >=0") }
87
88 min_rate_eps_ = rate;
90 }

References enabled_min_rate_eps_, GUM_ERROR, and min_rate_eps_.

Referenced by gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), gum::GibbsSampling< GUM_SCALAR >::GibbsSampling(), gum::SamplingInference< GUM_SCALAR >::SamplingInference(), and gum::learning::EMApproximationScheme::setMinEpsilonRate().

Here is the caller graph for this function:

◆ setPeriodSize()

INLINE void gum::ApproximationScheme::setPeriodSize ( Size p)
overridevirtualinherited

How many samples between two stopping is enable.

Parameters
pThe new period value.
Exceptions
OutOfBoundsRaised if p < 1.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 150 of file approximationScheme_inl.h.

150 {
151 if (p < 1) { GUM_ERROR(OutOfBounds, "p should be >=1") }
152
153 period_size_ = p;
154 }

References GUM_ERROR.

Referenced by gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), and gum::SamplingInference< GUM_SCALAR >::SamplingInference().

Here is the caller graph for this function:

◆ setStable()

void gum::learning::CIBasedLearning::setStable ( bool stable)
inherited

stable mode: defer edge removals until end of each depth (default: true)

Definition at line 112 of file CIBasedLearning.cpp.

112{ stable_ = stable; }

References stable_.

Referenced by ~CIBasedLearning().

Here is the caller graph for this function:

◆ setUCPriority()

void gum::learning::CIBasedLearning::setUCPriority ( UCPriority p)
inherited

collider candidate ordering (default: Standard)

Definition at line 118 of file CIBasedLearning.cpp.

118{ ucPriority_ = p; }

References ucPriority_.

Referenced by ~CIBasedLearning().

Here is the caller graph for this function:

◆ setVerbosity()

INLINE void gum::ApproximationScheme::setVerbosity ( bool v)
overridevirtualinherited

Set the verbosity on (true) or off (false).

Parameters
vIf true, then verbosity is turned on.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 159 of file approximationScheme_inl.h.

159{ verbosity_ = v; }
bool verbosity_
If true, verbosity is enabled.

References verbosity_.

Referenced by gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), gum::GibbsBNdistance< GUM_SCALAR >::GibbsBNdistance(), and gum::SamplingInference< GUM_SCALAR >::SamplingInference().

Here is the caller graph for this function:

◆ startOfPeriod()

INLINE bool gum::ApproximationScheme::startOfPeriod ( ) const
inherited

Returns true if we are at the beginning of a period (compute error is mandatory).

Returns
Returns true if we are at the beginning of a period (compute error is mandatory).

Definition at line 200 of file approximationScheme_inl.h.

200 {
201 if (current_step_ < burn_in_) { return false; }
202
203 if (period_size_ == 1) { return true; }
204
205 return ((current_step_ - burn_in_) % period_size_ == 0);
206 }

Referenced by continueApproximationScheme().

Here is the caller graph for this function:

◆ stateApproximationScheme()

INLINE IApproximationSchemeConfiguration::ApproximationSchemeSTATE gum::ApproximationScheme::stateApproximationScheme ( ) const
overridevirtualinherited

Returns the approximation scheme state.

Returns
Returns the approximation scheme state.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 165 of file approximationScheme_inl.h.

165 {
166 return current_state_;
167 }

Referenced by continueApproximationScheme(), history(), and nbrIterations().

Here is the caller graph for this function:

◆ stopApproximationScheme()

INLINE void gum::ApproximationScheme::stopApproximationScheme ( )
inherited

Stop the approximation scheme.

Definition at line 222 of file approximationScheme_inl.h.

Referenced by gum::learning::GreedyHillClimbing::learnStructure(), gum::learning::GreedyThickThinning::learnStructure(), gum::learning::LocalSearchWithTabuList::learnStructure(), and gum::credal::CNLoopyPropagation< GUM_SCALAR >::makeInferenceNodeToNeighbours_().

Here is the caller graph for this function:

◆ stopScheme_()

INLINE void gum::ApproximationScheme::stopScheme_ ( ApproximationSchemeSTATE new_state)
privateinherited

Stop the scheme given a new state.

Parameters
new_stateThe scheme new state.

Definition at line 231 of file approximationScheme_inl.h.

231 {
232 if (new_state == ApproximationSchemeSTATE::Continue) { return; }
233
234 if (new_state == ApproximationSchemeSTATE::Undefined) { return; }
235
236 current_state_ = new_state;
237 timer_.pause();
238
239 if (onStop.hasListener()) { GUM_EMIT1(onStop, messageApproximationScheme()); }
240 }
Signaler< std::string_view > onStop
Criteria messageApproximationScheme.
#define GUM_EMIT1(signal, arg1)
Definition signaler.h:289

References gum::IApproximationSchemeConfiguration::Continue, and gum::IApproximationSchemeConfiguration::Undefined.

Referenced by continueApproximationScheme(), and gum::credal::MultipleInferenceEngine< GUM_SCALAR, LazyPropagation< GUM_SCALAR > >::disableMaxIter().

Here is the caller graph for this function:

◆ ucPriority()

CIBasedLearning::UCPriority gum::learning::CIBasedLearning::ucPriority ( ) const
inherited

maximum conditioning set size; Size(-1) = unlimited (default)

Definition at line 120 of file CIBasedLearning.cpp.

120{ return ucPriority_; }

References ucPriority_.

Referenced by ~CIBasedLearning().

Here is the caller graph for this function:

◆ unshieldedTriples_()

std::vector< ThreePoints > gum::learning::ConstraintBasedLearning::unshieldedTriples_ ( const MixedGraph & graph)
protectedinherited

Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.

Definition at line 301 of file ConstraintBasedLearning.cpp.

301 {
302 std::vector< ThreePoints > triples;
303 for (NodeId z: graph) {
304 for (NodeId x: graph.neighbours(z)) {
305 for (NodeId y: graph.neighbours(z)) {
306 if (y < x && !graph.existsEdge(x, y) && !graph.existsArc(x, y)
307 && !graph.existsArc(y, x)) {
308 triples.emplace_back(x, y, z);
309 }
310 }
311 }
312 }
313 return triples;
314 }

Referenced by gum::learning::FCI::orientCollidersOnPAG_(), and gum::learning::CIBasedLearning::orientUnshieldedColliders_().

Here is the caller graph for this function:

◆ updateApproximationScheme()

INLINE void gum::ApproximationScheme::updateApproximationScheme ( unsigned int incr = 1)
inherited

◆ verbosity()

INLINE bool gum::ApproximationScheme::verbosity ( ) const
overridevirtualinherited

Returns true if verbosity is enabled.

Returns
Returns true if verbosity is enabled.

Implements gum::IApproximationSchemeConfiguration.

Definition at line 161 of file approximationScheme_inl.h.

161{ return verbosity_; }

References verbosity_.

Referenced by ApproximationScheme(), gum::learning::EMApproximationScheme::EMApproximationScheme(), and continueApproximationScheme().

Here is the caller graph for this function:

Member Data Documentation

◆ _emptySet_

const std::vector< NodeId > gum::learning::ConstraintBasedLearning::_emptySet_
protectedinherited

◆ _forbiddenGraph_

◆ _initialMarks_

HashTable< std::pair< NodeId, NodeId >, char > gum::learning::ConstraintBasedLearning::_initialMarks_
protectedinherited

◆ _latentCouples_

◆ _mandatoryGraph_

gum::DAG gum::learning::ConstraintBasedLearning::_mandatoryGraph_
protectedinherited

◆ _maxIndegree_

gum::Size gum::learning::ConstraintBasedLearning::_maxIndegree_ {std::numeric_limits< gum::Size >::max()}
privateinherited

Definition at line 204 of file ConstraintBasedLearning.h.

204{std::numeric_limits< gum::Size >::max()};

Referenced by ConstraintBasedLearning(), ConstraintBasedLearning(), isMaxIndegree_(), operator=(), operator=(), and setMaxIndegree().

◆ _maxLog_

int gum::learning::ConstraintBasedLearning::_maxLog_ {100}
protectedinherited

◆ alpha_

double gum::learning::CIBasedLearning::alpha_ = 0.05
protectedinherited

◆ burn_in_

Size gum::ApproximationScheme::burn_in_
protectedinherited

◆ current_epsilon_

double gum::ApproximationScheme::current_epsilon_
protectedinherited

Current epsilon.

Definition at line 378 of file approximationScheme.h.

Referenced by continueApproximationScheme().

◆ current_rate_

double gum::ApproximationScheme::current_rate_
protectedinherited

Current rate.

Definition at line 384 of file approximationScheme.h.

Referenced by continueApproximationScheme().

◆ current_state_

ApproximationSchemeSTATE gum::ApproximationScheme::current_state_
protectedinherited

The current state.

Definition at line 393 of file approximationScheme.h.

Referenced by ApproximationScheme(), continueApproximationScheme(), and initApproximationScheme().

◆ current_step_

◆ enabled_eps_

bool gum::ApproximationScheme::enabled_eps_
protectedinherited

If true, the threshold convergence is enabled.

Definition at line 402 of file approximationScheme.h.

Referenced by ApproximationScheme(), continueApproximationScheme(), disableEpsilon(), enableEpsilon(), isEnabledEpsilon(), and setEpsilon().

◆ enabled_max_iter_

bool gum::ApproximationScheme::enabled_max_iter_
protectedinherited

If true, the maximum iterations stopping criterion is enabled.

Definition at line 420 of file approximationScheme.h.

Referenced by ApproximationScheme(), continueApproximationScheme(), disableMaxIter(), enableMaxIter(), isEnabledMaxIter(), and setMaxIter().

◆ enabled_max_time_

bool gum::ApproximationScheme::enabled_max_time_
protectedinherited

If true, the timeout is enabled.

Definition at line 414 of file approximationScheme.h.

Referenced by ApproximationScheme(), continueApproximationScheme(), disableMaxTime(), enableMaxTime(), isEnabledMaxTime(), and setMaxTime().

◆ enabled_min_rate_eps_

bool gum::ApproximationScheme::enabled_min_rate_eps_
protectedinherited

If true, the minimal threshold for epsilon rate is enabled.

Definition at line 408 of file approximationScheme.h.

Referenced by ApproximationScheme(), continueApproximationScheme(), disableMinEpsilonRate(), enableMinEpsilonRate(), isEnabledMinEpsilonRate(), and setMinEpsilonRate().

◆ eps_

double gum::ApproximationScheme::eps_
protectedinherited

Threshold for convergence.

Definition at line 399 of file approximationScheme.h.

Referenced by ApproximationScheme(), continueApproximationScheme(), epsilon(), and setEpsilon().

◆ exhaustiveSepSet_

bool gum::learning::CIBasedLearning::exhaustiveSepSet_ = false
protectedinherited

◆ history_

std::vector< double > gum::ApproximationScheme::history_
protectedinherited

The scheme history, used only if verbosity == true.

Definition at line 396 of file approximationScheme.h.

Referenced by continueApproximationScheme().

◆ last_epsilon_

double gum::ApproximationScheme::last_epsilon_
protectedinherited

Last epsilon value.

Definition at line 381 of file approximationScheme.h.

Referenced by continueApproximationScheme().

◆ max_iter_

Size gum::ApproximationScheme::max_iter_
protectedinherited

The maximum iterations.

Definition at line 417 of file approximationScheme.h.

Referenced by ApproximationScheme(), continueApproximationScheme(), maxIter(), and setMaxIter().

◆ max_time_

double gum::ApproximationScheme::max_time_
protectedinherited

The timeout.

Definition at line 411 of file approximationScheme.h.

Referenced by ApproximationScheme(), continueApproximationScheme(), maxTime(), and setMaxTime().

◆ maxCondSetSize_

Size gum::learning::CIBasedLearning::maxCondSetSize_ = Size(-1)
protectedinherited

◆ maxPathLength_

Size gum::learning::FCI::maxPathLength_ = Size(-1)
private

Definition at line 165 of file FCI.h.

Referenced by FCI(), maxPathLength(), operator=(), operator=(), ruleR4_(), and setMaxPathLength().

◆ meekRules_

gum::MeekRules gum::learning::ConstraintBasedLearning::meekRules_
protectedinherited

Builds a complete MixedGraph on the nodes of template_graph, minus edges forbidden by structural constraints. Every constraint-based skeleton phase must start from this graph so forbidden pairs are never tested by CI.

Definition at line 176 of file ConstraintBasedLearning.h.

Referenced by learnDAG(), gum::learning::Miic::learnMixedStructure(), and learnPDAG().

◆ min_rate_eps_

double gum::ApproximationScheme::min_rate_eps_
protectedinherited

Threshold for the epsilon rate.

Definition at line 405 of file approximationScheme.h.

Referenced by ApproximationScheme(), continueApproximationScheme(), minEpsilonRate(), and setMinEpsilonRate().

◆ onProgress

◆ onStop

Signaler< std::string_view > gum::IApproximationSchemeConfiguration::onStop
inherited

Criteria messageApproximationScheme.

Definition at line 84 of file IApproximationSchemeConfiguration.h.

Referenced by gum::learning::IBNLearner::distributeStop().

◆ onStructuralModification

Signaler< gum::NodeId, gum::NodeId, std::string, std::string > gum::learning::ConstraintBasedLearning::onStructuralModification
inherited

Definition at line 145 of file ConstraintBasedLearning.h.

◆ period_size_

Size gum::ApproximationScheme::period_size_
protectedinherited

Checking criteria frequency.

Definition at line 426 of file approximationScheme.h.

Referenced by ApproximationScheme(), and periodSize().

◆ sepSet_

◆ stable_

bool gum::learning::CIBasedLearning::stable_ = true
protectedinherited

Definition at line 183 of file CIBasedLearning.h.

Referenced by CIBasedLearning(), learnSkeleton(), operator=(), operator=(), and setStable().

◆ test_

IndependenceTest* gum::learning::CIBasedLearning::test_ {nullptr}
protectedinherited

◆ timer_

◆ ucPriority_

UCPriority gum::learning::CIBasedLearning::ucPriority_ = UCPriority::Standard
protectedinherited

◆ verbosity_

bool gum::ApproximationScheme::verbosity_
protectedinherited

If true, verbosity is enabled.

Definition at line 429 of file approximationScheme.h.

Referenced by ApproximationScheme(), setVerbosity(), and verbosity().


The documentation for this class was generated from the following files: