All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.cmu.tetrad.search.GraspFci Maven / Gradle / Ivy

There is a newer version: 7.6.4
Show newest version
///////////////////////////////////////////////////////////////////////////////
// For information as to what this class does, see the Javadoc, below.       //i
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,       //
// 2007, 2008, 2009, 2010, 2014, 2015, 2022 by Peter Spirtes, Richard        //
// Scheines, Joseph Ramsey, and Clark Glymour.                               //
//                                                                           //
// This program is free software; you can redistribute it and/or modify      //
// it under the terms of the GNU General Public License as published by      //
// the Free Software Foundation; either version 2 of the License, or         //
// (at your option) any later version.                                       //
//                                                                           //
// This program is distributed in the hope that it will be useful,           //
// but WITHOUT ANY WARRANTY; without even the implied warranty of            //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
// GNU General Public License for more details.                              //
//                                                                           //
// You should have received a copy of the GNU General Public License         //
// along with this program; if not, write to the Free Software               //
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA //
///////////////////////////////////////////////////////////////////////////////
package edu.cmu.tetrad.search;

import edu.cmu.tetrad.data.Knowledge;
import edu.cmu.tetrad.graph.EdgeListGraph;
import edu.cmu.tetrad.graph.Graph;
import edu.cmu.tetrad.graph.GraphUtils;
import edu.cmu.tetrad.graph.Node;
import edu.cmu.tetrad.search.score.Score;
import edu.cmu.tetrad.search.utils.FciOrient;
import edu.cmu.tetrad.search.utils.SepsetProducer;
import edu.cmu.tetrad.search.utils.SepsetsGreedy;
import edu.cmu.tetrad.util.TetradLogger;

import java.util.List;

import static edu.cmu.tetrad.graph.GraphUtils.gfciExtraEdgeRemovalStep;

/**
 * 

Uses GRaSP in place of FGES for the initial step in the GFCI algorithm. * This tends to produce a accurate PAG than GFCI as a result, for the latent variables case. This is a simple * substitution; the reference for GFCI is here:

*

J.M. Ogarrio and P. Spirtes and J. Ramsey, "A Hybrid Causal Search Algorithm * for Latent Variable Models," JMLR 2016. Here, BOSS has been substituted for FGES.

* *

For the first step, the GRaSP algorithm is used, with the same * modifications as in the GFCI algorithm.

* *

For the second step, the FCI final orientation algorithm is used, with the same * modifications as in the GFCI algorithm.

* *

For GRaSP only a score is needed, but there are steps in GFCI that require * a test, so for this method, both a test and a score need to be given.

* *

This class is configured to respect knowledge of forbidden and required * edges, including knowledge of temporal tiers.

* * @author josephramsey * @author bryanandrews * @see Grasp * @see GFci * @see FciOrient * @see Knowledge */ public final class GraspFci implements IGraphSearch { // The conditional independence test. private final IndependenceTest independenceTest; // The logger to use. private final TetradLogger logger = TetradLogger.getInstance(); // The score. private final Score score; // The background knowledge. private Knowledge knowledge = new Knowledge(); // Flag for the complete rule set, true if one should use the complete rule set, false otherwise. private boolean completeRuleSetUsed = true; // The maximum length for any discriminating path. -1 if unlimited; otherwise, a positive integer. private int maxPathLength = -1; // True iff verbose output should be printed. private boolean verbose; private int numStarts = 1; private int depth = -1; private boolean useRaskuttiUhler = false; private boolean useDataOrder = true; private boolean useScore = true; private boolean doDiscriminatingPathRule = true; private boolean ordered = false; private int uncoveredDepth = 1; private int nonSingularDepth = 1; public GraspFci(IndependenceTest test, Score score) { if (score == null) { throw new NullPointerException(); } this.score = score; this.independenceTest = test; } /** * Run the search and return s a PAG. * * @return The PAG. */ public Graph search() { List nodes = this.independenceTest.getVariables(); if (nodes == null) { throw new NullPointerException("Nodes from test were null."); } this.logger.log("info", "Starting FCI algorithm."); this.logger.log("info", "Independence test = " + this.independenceTest + "."); // The PAG being constructed. // Run GRaSP to get a CPDAG (like GFCI with FGES)... Grasp alg = new Grasp(independenceTest, score); alg.setOrdered(ordered); alg.setUseScore(useScore); alg.setUseRaskuttiUhler(useRaskuttiUhler); alg.setUseDataOrder(useDataOrder); int graspDepth = 3; alg.setDepth(graspDepth); alg.setUncoveredDepth(uncoveredDepth); alg.setNonSingularDepth(nonSingularDepth); alg.setNumStarts(numStarts); alg.setVerbose(verbose); List variables = this.score.getVariables(); assert variables != null; alg.bestOrder(variables); Graph graph = alg.getGraph(true); // Get the DAG // Knowledge knowledge2 = new Knowledge(knowledge); Graph referenceDag = new EdgeListGraph(graph); // GFCI extra edge removal step... SepsetProducer sepsets = new SepsetsGreedy(graph, this.independenceTest, null, this.depth, knowledge); gfciExtraEdgeRemovalStep(graph, referenceDag, nodes, sepsets); GraphUtils.gfciR0(graph, referenceDag, sepsets, knowledge); FciOrient fciOrient = new FciOrient(sepsets); fciOrient.setCompleteRuleSetUsed(this.completeRuleSetUsed); fciOrient.setMaxPathLength(this.maxPathLength); fciOrient.setDoDiscriminatingPathColliderRule(this.doDiscriminatingPathRule); fciOrient.setDoDiscriminatingPathTailRule(this.doDiscriminatingPathRule); fciOrient.setVerbose(verbose); fciOrient.setKnowledge(knowledge); fciOrient.doFinalOrientation(graph); GraphUtils.replaceNodes(graph, this.independenceTest.getVariables()); return graph; } /** * Sets the knowledge used in search. * * @param knowledge This knowledge. */ public void setKnowledge(Knowledge knowledge) { this.knowledge = new Knowledge(knowledge); } /** * Sets whether Zhang's complete rules set is used. * * @param completeRuleSetUsed set to true if Zhang's complete rule set should be used, false if only R1-R4 (the rule * set of the original FCI) should be used. False by default. */ public void setCompleteRuleSetUsed(boolean completeRuleSetUsed) { this.completeRuleSetUsed = completeRuleSetUsed; } /** * Sets the maximum length of any discriminating path searched. * * @param maxPathLength the maximum length of any discriminating path, or -1 if unlimited. */ public void setMaxPathLength(int maxPathLength) { if (maxPathLength < -1) { throw new IllegalArgumentException("Max path length must be -1 (unlimited) or >= 0: " + maxPathLength); } this.maxPathLength = maxPathLength; } /** * Sets whether verbose output should be printed. * * @param verbose True, if so. */ public void setVerbose(boolean verbose) { this.verbose = verbose; } public void setNumStarts(int numStarts) { this.numStarts = numStarts; } public void setDepth(int depth) { this.depth = depth; } public void setUseRaskuttiUhler(boolean useRaskuttiUhler) { this.useRaskuttiUhler = useRaskuttiUhler; } public void setUseDataOrder(boolean useDataOrder) { this.useDataOrder = useDataOrder; } public void setUseScore(boolean useScore) { this.useScore = useScore; } public void setDoDiscriminatingPathRule(boolean doDiscriminatingPathRule) { this.doDiscriminatingPathRule = doDiscriminatingPathRule; } public void setSingularDepth(int uncoveredDepth) { if (uncoveredDepth < -1) throw new IllegalArgumentException("Uncovered depth should be >= -1."); this.uncoveredDepth = uncoveredDepth; } public void setNonSingularDepth(int nonSingularDepth) { if (nonSingularDepth < -1) throw new IllegalArgumentException("Non-singular depth should be >= -1."); this.nonSingularDepth = nonSingularDepth; } public void setOrdered(boolean ordered) { this.ordered = ordered; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy