edu.cmu.tetrad.search.work_in_progress.SampleVcpcFast Maven / Gradle / Ivy
The newest version!
///////////////////////////////////////////////////////////////////////////////
// For information as to what this class does, see the Javadoc, below. //
// 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.work_in_progress;
import edu.cmu.tetrad.data.CovarianceMatrix;
import edu.cmu.tetrad.data.DataSet;
import edu.cmu.tetrad.data.ICovarianceMatrix;
import edu.cmu.tetrad.data.Knowledge;
import edu.cmu.tetrad.graph.*;
import edu.cmu.tetrad.regression.Regression;
import edu.cmu.tetrad.regression.RegressionDataset;
import edu.cmu.tetrad.regression.RegressionResult;
import edu.cmu.tetrad.search.IGraphSearch;
import edu.cmu.tetrad.search.IndependenceTest;
import edu.cmu.tetrad.search.test.IndTestFisherZ;
import edu.cmu.tetrad.search.utils.GraphSearchUtils;
import edu.cmu.tetrad.search.utils.LogUtilsSearch;
import edu.cmu.tetrad.search.utils.MeekRules;
import edu.cmu.tetrad.sem.SemIm;
import edu.cmu.tetrad.sem.SemPm;
import edu.cmu.tetrad.util.ChoiceGenerator;
import edu.cmu.tetrad.util.CombinationGenerator;
import edu.cmu.tetrad.util.MillisecondTimes;
import edu.cmu.tetrad.util.TetradLogger;
import java.util.*;
/**
* Implements a conservative version of PC, in which the Markov condition is assumed but faithfulness is tested
* locally.
*
* @author josephramsey (this version).
* @version $Id: $Id
*/
public final class SampleVcpcFast implements IGraphSearch {
/**
* The independence test used for the PC search.
*/
private final IndependenceTest independenceTest;
/**
* The logger for this class. The config needs to be set.
*/
private final TetradLogger logger = TetradLogger.getInstance();
private final DataSet dataSet;
private final ICovarianceMatrix covMatrix;
/**
* Forbidden and required edges for the search.
*/
private Knowledge knowledge = new Knowledge();
/**
* The maximum number of nodes conditioned on in the search.
*/
private int depth = 1000;
private Graph graph;
/**
* Elapsed time of last search.
*/
private long elapsedTime;
/**
* Set of unshielded colliders from the triple orientation step.
*/
private Set colliderTriples;
/**
* Set of unshielded noncolliders from the triple orientation step.
*/
private Set noncolliderTriples;
/**
* Set of ambiguous unshielded triples.
*/
private Set ambiguousTriples;
private Set definitelyNonadjacencies;
private boolean guaranteeCpdag;
/**
* The sepsets.
*/
private Map> apparentlyNonadjacencies;
/**
* Whether verbose output about independencies is output.
*/
private boolean verbose;
private SemPm semPm;
private SemIm semIm;
//=============================CONSTRUCTORS==========================//
/**
* Constructs a CPC algorithm that uses the given independence test as oracle. This does not make a copy of the
* independence test, for fear of duplicating the data set!
*
* @param independenceTest a {@link edu.cmu.tetrad.search.IndependenceTest} object
*/
public SampleVcpcFast(IndependenceTest independenceTest) {
if (independenceTest == null) {
throw new NullPointerException();
}
if (!(independenceTest instanceof IndTestFisherZ)) {
throw new IllegalArgumentException("Need Fisher Z test to proceed with algorithm");
}
this.independenceTest = independenceTest;
this.dataSet = (DataSet) independenceTest.getData();
this.covMatrix = new CovarianceMatrix(this.dataSet);
}
//==============================PUBLIC METHODS========================//
// Constraints to guarantee future path conditions met. After traversing the entire path,
// returns last node on path when satisfied, stops otherwise.
private static Node traverseFuturePath(Node node, Edge edge1, Edge edge2) {
Endpoint E1 = edge1.getProximalEndpoint(node);
Endpoint E2 = edge2.getProximalEndpoint(node);
Endpoint E3 = edge2.getDistalEndpoint(node);
Endpoint E4 = edge1.getDistalEndpoint(node);
if (E1 == Endpoint.ARROW && E2 == Endpoint.ARROW && E3 == Endpoint.TAIL) {
return null;
}
if (E4 == Endpoint.ARROW) {
return null;
}
if (E4 == Endpoint.TAIL && E1 == Endpoint.TAIL && E2 == Endpoint.TAIL && E3 == Endpoint.TAIL) {
return null;
}
return edge2.getDistalNode(node);
}
// Takes a triple n1-n2-child and adds child to futureNodes set if satisfies constraints for future.
// Uses traverseFuturePath to add nodes to set.
/**
* futureNodeVisit.
*
* @param graph a {@link edu.cmu.tetrad.graph.Graph} object
* @param b a {@link edu.cmu.tetrad.graph.Node} object
* @param path a {@link java.util.LinkedList} object
* @param futureNodes a {@link java.util.Set} object
*/
public static void futureNodeVisit(Graph graph, Node b, LinkedList path, Set futureNodes) {
path.addLast(b);
futureNodes.add(b);
for (Edge edge2 : graph.getEdges(b)) {
Node c;
int size = path.size();
if (path.size() < 2) {
c = edge2.getDistalNode(b);
} else {
Node a = path.get(size - 2);
Edge edge1 = graph.getEdge(a, b);
c = SampleVcpcFast.traverseFuturePath(b, edge1, edge2);
}
if (c == null) {
continue;
}
if (path.contains(c)) {
continue;
}
SampleVcpcFast.futureNodeVisit(graph, c, path, futureNodes);
}
path.removeLast();
}
/**
* isArrowheadAllowed1.
*
* @param from a {@link edu.cmu.tetrad.graph.Node} object
* @param to a {@link edu.cmu.tetrad.graph.Node} object
* @param knowledge a {@link edu.cmu.tetrad.data.Knowledge} object
* @return a boolean
*/
public static boolean isArrowheadAllowed1(Node from, Node to,
Knowledge knowledge) {
return knowledge == null || !knowledge.isRequired(to.toString(), from.toString()) &&
!knowledge.isForbidden(from.toString(), to.toString());
}
/**
* Getter for the field semIm
.
*
* @return a {@link edu.cmu.tetrad.sem.SemIm} object
*/
public SemIm getSemIm() {
return this.semIm;
}
/**
* Setter for the field semIm
.
*
* @param semIm a {@link edu.cmu.tetrad.sem.SemIm} object
*/
public void setSemIm(SemIm semIm) {
this.semIm = semIm;
}
/**
* isMeekPreventCycles.
*
* @return true just in case edges will not be added if they would create cycles.
*/
public boolean isGuaranteeCpdag() {
return this.guaranteeCpdag;
}
/**
* Sets to true just in case the output is guaranteed to be compatible with a CPDAG--i.e.,
* no bidirected edges and no actual or implied cycles due to the Meek rules.
*
* @param setGuaranteeCpdag a boolean
*/
public void setMeekPreventCycles(boolean setGuaranteeCpdag) {
this.guaranteeCpdag = setGuaranteeCpdag;
}
/**
* Getter for the field elapsedTime
.
*
* @return the elapsed time of search in milliseconds, after search()
has been run.
*/
public long getElapsedTime() {
return this.elapsedTime;
}
/**
* Getter for the field knowledge
.
*
* @return the knowledge specification used in the search. Non-null.
*/
public Knowledge getKnowledge() {
return this.knowledge;
}
/**
* Sets the knowledge specification used in the search. Non-null.
*
* @param knowledge a {@link edu.cmu.tetrad.data.Knowledge} object
*/
public void setKnowledge(Knowledge knowledge) {
this.knowledge = new Knowledge(knowledge);
}
/**
* Getter for the field independenceTest
.
*
* @return the independence test used in the search, set in the constructor. This is not returning a copy, for fear
* of duplicating the data set!
*/
public IndependenceTest getIndependenceTest() {
return this.independenceTest;
}
/**
* Getter for the field depth
.
*
* @return the depth of the search--that is, the maximum number of variables conditioned on in any conditional
* independence test.
*/
public int getDepth() {
return this.depth;
}
/**
* Sets the maximum number of variables conditioned on in any conditional independence test. If set to -1, the value
* of 1000 will be used. May not be set to Integer.MAX_VALUE, due to a Java bug on multi-core systems.
*
* @param depth a int
*/
public void setDepth(int depth) {
if (depth < -1) {
throw new IllegalArgumentException("Depth must be -1 or >= 0: " + depth);
}
if (depth == Integer.MAX_VALUE) {
throw new IllegalArgumentException("Depth must not be Integer.MAX_VALUE, " +
"due to a known bug.");
}
this.depth = depth;
}
/**
* Getter for the field ambiguousTriples
.
*
* @return the set of ambiguous triples found during the most recent run of the algorithm. Non-null after a call to
* search()
.
*/
public Set getAmbiguousTriples() {
return new HashSet<>(this.ambiguousTriples);
}
/**
* Getter for the field colliderTriples
.
*
* @return the set of collider triples found during the most recent run of the algorithm. Non-null after a call to
* search()
.
*/
public Set getColliderTriples() {
return new HashSet<>(this.colliderTriples);
}
/**
* Getter for the field noncolliderTriples
.
*
* @return the set of noncollider triples found during the most recent run of the algorithm. Non-null after a call
* to search()
.
*/
public Set getNoncolliderTriples() {
return new HashSet<>(this.noncolliderTriples);
}
//==========================PRIVATE METHODS===========================//
/**
* getAdjacencies.
*
* @return a {@link java.util.Set} object
*/
public Set getAdjacencies() {
return new HashSet<>(this.graph.getEdges());
}
// Takes CPDAGs and, with respect to a node and its boundary, finds all possible combinations of orientations
// of its boundary such that no new colliders are created. For each combination, a new CPDAG is added to the
// list dagCPDAGs.
/**
* getApparentNonadjacencies.
*
* @return a {@link java.util.Set} object
*/
public Set getApparentNonadjacencies() {
return new HashSet<>(this.apparentlyNonadjacencies.keySet());
}
/**
* getDefiniteNonadjacencies.
*
* @return a {@link java.util.Set} object
*/
public Set getDefiniteNonadjacencies() {
return new HashSet<>(this.definitelyNonadjacencies);
}
/**
* search.
*
* @return a {@link edu.cmu.tetrad.graph.Graph} object
*/
public Graph search() {
if (verbose) {
TetradLogger.getInstance().log("Starting VCCPC algorithm");
TetradLogger.getInstance().log("Independence test = " + getIndependenceTest() + ".");
}
this.ambiguousTriples = new HashSet<>();
this.colliderTriples = new HashSet<>();
this.noncolliderTriples = new HashSet<>();
VcFas fas = new VcFas(getIndependenceTest());
this.definitelyNonadjacencies = new HashSet<>();
long startTime = MillisecondTimes.timeMillis();
List allNodes = getIndependenceTest().getVariables();
fas.setKnowledge(getKnowledge());
fas.setDepth(getDepth());
fas.setVerbose(this.verbose);
// Note that we are ignoring the sepset map returned by this method
// on purpose; it is not used in this search.
this.graph = fas.search();
this.apparentlyNonadjacencies = fas.getApparentlyNonadjacencies();
if (isDoOrientation()) {
if (this.verbose) {
System.out.println("CPC orientation...");
}
GraphSearchUtils.pcOrientbk(this.knowledge, this.graph, allNodes, verbose);
orientUnshieldedTriples(this.knowledge, getIndependenceTest(), getDepth());
// orientUnshieldedTriplesConcurrent(knowledge, getIndependenceTest(), getMaxIndegree());
MeekRules meekRules = new MeekRules();
meekRules.setMeekPreventCycles(this.guaranteeCpdag);
meekRules.setKnowledge(this.knowledge);
meekRules.orientImplied(this.graph);
}
List ambiguousTriples = new ArrayList<>(this.graph.getAmbiguousTriples());
int[] dims = new int[ambiguousTriples.size()];
for (int i = 0; i < ambiguousTriples.size(); i++) {
dims[i] = 2;
}
List CPDAGs = new ArrayList<>();
Map> newColliders = new IdentityHashMap<>();
Map> newNonColliders = new IdentityHashMap<>();
// Using combination generator to generate a list of combinations of ambiguous triples dismabiguated into colliders
// and non-colliders. The combinations are added as graphs to the list CPDAGs. The graphs are then subject to
// basic rules to ensure consistent CPDAGs.
CombinationGenerator generator = new CombinationGenerator(dims);
int[] combination;
while ((combination = generator.next()) != null) {
Graph _graph = new EdgeListGraph(this.graph);
newColliders.put(_graph, new ArrayList<>());
newNonColliders.put(_graph, new ArrayList<>());
for (int k = 0; k < combination.length; k++) {
// System.out.println("k = " + combination[k]);
Triple triple = ambiguousTriples.get(k);
_graph.removeAmbiguousTriple(triple.getX(), triple.getY(), triple.getZ());
if (combination[k] == 0) {
newColliders.get(_graph).add(triple);
// System.out.println(newColliders.get(_graph));
Node x = triple.getX();
Node y = triple.getY();
Node z = triple.getZ();
_graph.setEndpoint(x, y, Endpoint.ARROW);
_graph.setEndpoint(z, y, Endpoint.ARROW);
}
if (combination[k] == 1) {
newNonColliders.get(_graph).add(triple);
}
}
CPDAGs.add(_graph);
}
/// Takes CPDAGs and runs them through basic constraints to ensure consistent CPDAGs (e.g. no cycles, no bidirected edges).
GRAPH:
for (Graph graph : new ArrayList<>(CPDAGs)) {
List colliders = newColliders.get(graph);
List nonColliders = newNonColliders.get(graph);
for (Triple triple : colliders) {
Node x = triple.getX();
Node y = triple.getY();
Node z = triple.getZ();
if (graph.getEdge(x, y).pointsTowards(x) || (graph.getEdge(y, z).pointsTowards(z))) {
CPDAGs.remove(graph);
continue GRAPH;
}
}
for (Triple triple : colliders) {
Node x = triple.getX();
Node y = triple.getY();
Node z = triple.getZ();
graph.setEndpoint(x, y, Endpoint.ARROW);
graph.setEndpoint(z, y, Endpoint.ARROW);
}
for (Triple triple : nonColliders) {
Node x = triple.getX();
Node y = triple.getY();
Node z = triple.getZ();
if (graph.getEdge(x, y).pointsTowards(y)) {
graph.removeEdge(y, z);
graph.addDirectedEdge(y, z);
}
if (graph.getEdge(y, z).pointsTowards(y)) {
graph.removeEdge(x, y);
graph.addDirectedEdge(y, x);
}
}
for (Edge edge : graph.getEdges()) {
Node x = edge.getNode1();
Node y = edge.getNode2();
if (Edges.isBidirectedEdge(edge)) {
graph.removeEdge(x, y);
graph.addUndirectedEdge(x, y);
}
}
MeekRules rules = new MeekRules();
rules.orientImplied(graph);
if (graph.paths().existsDirectedCycle()) {
CPDAGs.remove(graph);
}
}
// 4/8/15 Local Relative Markov (M2)
MARKOV:
for (Edge edge : this.apparentlyNonadjacencies.keySet()) {
Node x = edge.getNode1();
Node y = edge.getNode2();
for (Graph _graph : new ArrayList<>(CPDAGs)) {
Set boundaryX = new HashSet<>(boundary(x, _graph));
Set boundaryY = new HashSet<>(boundary(y, _graph));
Set futureX = new HashSet<>(future(x, _graph));
Set futureY = new HashSet<>(future(y, _graph));
if (y == x) {
continue;
}
if (boundaryX.contains(y) || boundaryY.contains(x)) {
continue;
}
IndependenceTest test = this.independenceTest;
if (!futureX.contains(y)) {
if (!test.checkIndependence(x, y, boundaryX).isIndependent()) {
continue MARKOV;
}
}
if (!futureY.contains(x)) {
if (!test.checkIndependence(y, x, boundaryY).isIndependent()) {
continue MARKOV;
}
}
}
this.definitelyNonadjacencies.add(edge);
// apparentlyNonadjacencies.remove(edge);
}
for (Edge edge : this.definitelyNonadjacencies) {
if (this.apparentlyNonadjacencies.containsKey(edge)) {
this.apparentlyNonadjacencies.keySet().remove(edge);
}
}
setSemIm(this.semIm);
Regression sampleRegression = new RegressionDataset(this.dataSet);
System.out.println(sampleRegression.getGraph());
this.graph = GraphUtils.replaceNodes(this.graph, this.dataSet.getVariables());
Map sampleRegress = new HashMap<>();
Map edgeCoefs = new HashMap<>();
ESTIMATION:
for (Node z : this.graph.getNodes()) {
Set adj = getAdj(z, this.graph);
for (Edge edge : this.apparentlyNonadjacencies.keySet()) {
if (z == edge.getNode1() || z == edge.getNode2()) {
for (Edge adjacency : adj) {
// return Unknown and go to next Z
sampleRegress.put(adjacency, null);
Node a = adjacency.getNode1();
Node b = adjacency.getNode2();
if (this.semIm.existsEdgeCoef(a, b)) {
Double c = this.semIm.getEdgeCoef(a, b);
edgeCoefs.put(adjacency, c);
} else {
edgeCoefs.put(adjacency, 0.0);
}
}
continue ESTIMATION;
}
}
for (Edge nonadj : this.definitelyNonadjacencies) {
if (nonadj.getNode1() == z || nonadj.getNode2() == z) {
// return 0 for e
double[] d = {0, 0};
sampleRegress.put(nonadj, d);
Node a = nonadj.getNode1();
Node b = nonadj.getNode2();
if (this.semIm.existsEdgeCoef(a, b)) {
Double c = this.semIm.getEdgeCoef(a, b);
edgeCoefs.put(nonadj, c);
} else {
edgeCoefs.put(nonadj, 0.0);
}
}
}
Set parentsOfZ = new HashSet<>();
Set _adj = getAdj(z, this.graph);
for (Edge _adjacency : _adj) {
if (!_adjacency.isDirected()) {
for (Edge adjacency : adj) {
sampleRegress.put(adjacency, null);
Node a = adjacency.getNode1();
Node b = adjacency.getNode2();
if (this.semIm.existsEdgeCoef(a, b)) {
Double c = this.semIm.getEdgeCoef(a, b);
edgeCoefs.put(adjacency, c);
} else {
edgeCoefs.put(adjacency, 0.0);
}
}
}
if (_adjacency.pointsTowards(z)) {
parentsOfZ.add(_adjacency);
}
}
for (Edge edge : parentsOfZ) {
if (edge.pointsTowards(edge.getNode2())) {
RegressionResult result = sampleRegression.regress(edge.getNode2(), edge.getNode1());
System.out.println(result);
double[] d = result.getCoef();
sampleRegress.put(edge, d);
Node a = edge.getNode1();
Node b = edge.getNode2();
if (this.semIm.existsEdgeCoef(a, b)) {
Double c = this.semIm.getEdgeCoef(a, b);
edgeCoefs.put(edge, c);
} else {
edgeCoefs.put(edge, 0.0);
}
}
}
}
System.out.println("All IM: " + this.semIm + "Finish");
System.out.println("Just IM coefs: " + this.semIm.getEdgeCoef());
System.out.println("IM Coef Map: " + edgeCoefs);
System.out.println("Regress Coef Map: " + sampleRegress);
for (Edge edge : sampleRegress.keySet()) {
System.out.println(" Sample Regression: " + edge + Arrays.toString(sampleRegress.get(edge)));
}
for (Edge edge : this.graph.getEdges()) {
System.out.println("Sample edge: " + Arrays.toString(sampleRegress.get(edge)));
}
//
//
System.out.println("Sample VCPC:");
System.out.println("# of CPDAGs: " + CPDAGs.size());
long endTime = MillisecondTimes.timeMillis();
this.elapsedTime = endTime - startTime;
System.out.println("Search Time (seconds):" + (this.elapsedTime) / 1000 + " s");
System.out.println("Search Time (milli):" + this.elapsedTime + " ms");
System.out.println("# of Apparent Nonadj: " + this.apparentlyNonadjacencies.size());
System.out.println("# of Definite Nonadj: " + this.definitelyNonadjacencies.size());
if (verbose) {
TetradLogger.getInstance().log("\n Apparent Non-adjacencies" + this.apparentlyNonadjacencies);
TetradLogger.getInstance().log("\n Definite Non-adjacencies" + this.definitelyNonadjacencies);
TetradLogger.getInstance().log("Disambiguated CPDAGs: " + CPDAGs);
TetradLogger.getInstance().log("Elapsed time = " + (this.elapsedTime) / 1000. + " s");
TetradLogger.getInstance().log("Finishing CPC algorithm.");
logTriples();
}
return this.graph;
}
/**
* getCov.
*
* @return a {@link edu.cmu.tetrad.data.ICovarianceMatrix} object
*/
public ICovarianceMatrix getCov() {
return this.covMatrix;
}
private Set getAdj(Node node, Graph graph) {
Set adj = new HashSet<>();
for (Edge edge : graph.getEdges()) {
if (node == edge.getNode1()) {
adj.add(edge);
}
if (node == edge.getNode2()) {
adj.add(edge);
}
}
return adj;
}
// For a node x, adds nodes y such that either y-x or y->x to the boundary of x
private Set boundary(Node x, Graph graph) {
Set boundary = new HashSet<>();
List adj = graph.getAdjacentNodes(x);
for (Node y : adj) {
if (graph.isParentOf(y, x) || Edges.isUndirectedEdge(graph.getEdge(x, y))) {
boundary.add(y);
}
}
return boundary;
}
// For a node x, adds nodes y such that either x->..->y or x-..-..->..->y to the future of x
private Set future(Node x, Graph graph) {
Set futureNodes = new HashSet<>();
LinkedList path = new LinkedList<>();
SampleVcpcFast.futureNodeVisit(graph, x, path, futureNodes);
futureNodes.remove(x);
List adj = graph.getAdjacentNodes(x);
for (Node y : adj) {
if (graph.isParentOf(y, x) || Edges.isUndirectedEdge(graph.getEdge(x, y))) {
futureNodes.remove(y);
}
}
return futureNodes;
}
// Sample Version of Step 3 of VCPC.
private void logTriples() {
if (verbose) {
TetradLogger.getInstance().log("\nCollider triples:");
for (Triple triple : this.colliderTriples) {
TetradLogger.getInstance().log("Collider: " + triple);
}
TetradLogger.getInstance().log("\nNoncollider triples:");
for (Triple triple : this.noncolliderTriples) {
TetradLogger.getInstance().log("Noncollider: " + triple);
}
TetradLogger.getInstance().log("\nAmbiguous triples (i.e. list of triples for which " +
"\nthere is ambiguous data about whether they are colliders or not):");
for (Triple triple : getAmbiguousTriples()) {
TetradLogger.getInstance().log("Ambiguous: " + triple);
}
}
}
private void orientUnshieldedTriples(Knowledge knowledge,
IndependenceTest test, int depth) {
TetradLogger.getInstance().log("Starting Collider Orientation:");
// System.out.println("orientUnshieldedTriples 1");
this.colliderTriples = new HashSet<>();
this.noncolliderTriples = new HashSet<>();
this.ambiguousTriples = new HashSet<>();
List nodes = this.graph.getNodes();
for (Node y : nodes) {
List adjacentNodes = new ArrayList<>(this.graph.getAdjacentNodes(y));
if (adjacentNodes.size() < 2) {
continue;
}
ChoiceGenerator cg = new ChoiceGenerator(adjacentNodes.size(), 2);
int[] combination;
while ((combination = cg.next()) != null) {
Node x = adjacentNodes.get(combination[0]);
Node z = adjacentNodes.get(combination[1]);
if (this.graph.isAdjacentTo(x, z)) {
continue;
}
GraphSearchUtils.CpcTripleType type = GraphSearchUtils.getCpcTripleType(x, y, z, test, depth, graph);
if (type == GraphSearchUtils.CpcTripleType.COLLIDER) {
if (this.colliderAllowed(x, y, z, knowledge)) {
graph.setEndpoint(x, y, Endpoint.ARROW);
graph.setEndpoint(z, y, Endpoint.ARROW);
String message = LogUtilsSearch.colliderOrientedMsg(x, y, z);
TetradLogger.getInstance().log(message);
}
colliderTriples.add(new Triple(x, y, z));
} else if (type == GraphSearchUtils.CpcTripleType.AMBIGUOUS) {
Triple triple = new Triple(x, y, z);
ambiguousTriples.add(triple);
graph.addAmbiguousTriple(triple.getX(), triple.getY(), triple.getZ());
Edge edge = Edges.undirectedEdge(x, z);
definitelyNonadjacencies.add(edge);
} else {
noncolliderTriples.add(new Triple(x, y, z));
}
}
}
TetradLogger.getInstance().log("Finishing Collider Orientation.");
}
private boolean colliderAllowed(Node x, Node y, Node z, Knowledge knowledge) {
return SampleVcpcFast.isArrowheadAllowed1(x, y, knowledge) &&
SampleVcpcFast.isArrowheadAllowed1(z, y, knowledge);
}
/**
* isDoOrientation.
*
* @return a boolean
*/
public boolean isDoOrientation() {
return true;
}
/**
* The graph that's constructed during the search.
*
* @return a {@link edu.cmu.tetrad.graph.Graph} object
*/
public Graph getGraph() {
return this.graph;
}
/**
* Setter for the field graph
.
*
* @param graph a {@link edu.cmu.tetrad.graph.Graph} object
*/
public void setGraph(Graph graph) {
this.graph = graph;
}
/**
* Setter for the field verbose
.
*
* @param verbose a boolean
*/
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
/**
* Getter for the field semPm
.
*
* @return a {@link edu.cmu.tetrad.sem.SemPm} object
*/
public SemPm getSemPm() {
return this.semPm;
}
/**
* Setter for the field semPm
.
*
* @param semPm a {@link edu.cmu.tetrad.sem.SemPm} object
*/
public void setSemPm(SemPm semPm) {
this.semPm = semPm;
}
}