public boolean isIndependent(Node x, Node y, List<Node> z) { int[] all = new int[z.size() + 2]; all[0] = variablesMap.get(x); all[1] = variablesMap.get(y); for (int i = 0; i < z.size(); i++) { all[i + 2] = variablesMap.get(z.get(i)); } int sampleSize = data.get(0).rows(); List<Double> pValues = new ArrayList<Double>(); for (int m = 0; m < ncov.size(); m++) { TetradMatrix _ncov = ncov.get(m).getSelection(all, all); TetradMatrix inv = _ncov.inverse(); double r = -inv.get(0, 1) / sqrt(inv.get(0, 0) * inv.get(1, 1)); double fisherZ = sqrt(sampleSize - z.size() - 3.0) * 0.5 * (Math.log(1.0 + r) - Math.log(1.0 - r)); double pValue; if (Double.isInfinite(fisherZ)) { pValue = 0; } else { pValue = 2.0 * (1.0 - RandomUtil.getInstance().normalCdf(0, 1, abs(fisherZ))); } pValues.add(pValue); } double _cutoff = alpha; if (fdr) { _cutoff = StatUtils.fdrCutoff(alpha, pValues, false); } Collections.sort(pValues); int index = (int) round((1.0 - percent) * pValues.size()); this.pValue = pValues.get(index); // if (this.pValue == 0) { // System.out.println("Zero pvalue "+ SearchLogUtils.independenceFactMsg(x, y, z, // getPValue())); // } boolean independent = this.pValue > _cutoff; if (verbose) { if (independent) { TetradLogger.getInstance() .log("independencies", SearchLogUtils.independenceFactMsg(x, y, z, getPValue())); // System.out.println(SearchLogUtils.independenceFactMsg(x, y, z, getPValue())); } else { TetradLogger.getInstance() .log("dependencies", SearchLogUtils.dependenceFactMsg(x, y, z, getPValue())); } } return independent; }
/** * Step C of PC; orients colliders using specified sepset. That is, orients x *-* y *-* z as x *-> * y <-* z just in case y is in Sepset({x, z}). */ public Map<Triple, Double> findCollidersUsingSepsets( SepsetProducer sepsetProducer, Graph graph, boolean verbose, IKnowledge knowledge) { TetradLogger.getInstance().log("details", "Starting Collider Orientation:"); Map<Triple, Double> colliders = new HashMap<>(); System.out.println("Looking for colliders"); List<Node> nodes = graph.getNodes(); for (Node b : nodes) { List<Node> adjacentNodes = graph.getAdjacentNodes(b); if (adjacentNodes.size() < 2) { continue; } ChoiceGenerator cg = new ChoiceGenerator(adjacentNodes.size(), 2); int[] combination; while ((combination = cg.next()) != null) { Node a = adjacentNodes.get(combination[0]); Node c = adjacentNodes.get(combination[1]); // Skip triples that are shielded. if (graph.isAdjacentTo(a, c)) { continue; } List<Node> sepset = sepsetProducer.getSepset(a, c); if (sepset == null) continue; // if (sepsetProducer.getPValue() < 0.5) continue; if (!sepset.contains(b)) { if (verbose) { // boolean dsep = this.dsep.isIndependent(a, c); // System.out.println("QQQ p = " + independenceTest.getPValue() + // " " + dsep); System.out.println( "\nCollider orientation <" + a + ", " + b + ", " + c + "> sepset = " + sepset); } colliders.put(new Triple(a, b, c), sepsetProducer.getPValue()); TetradLogger.getInstance() .log("colliderOrientations", SearchLogUtils.colliderOrientedMsg(a, b, c, sepset)); } } } TetradLogger.getInstance().log("details", "Finishing Collider Orientation."); System.out.println("Done finding colliders"); return colliders; }
/** * Completes a pattern that was modified by an insertion/deletion operator Based on the algorithm * described on Appendix C of (Chickering, 2002). */ private void rebuildPattern(Graph graph) { SearchGraphUtils.basicPattern(graph, false); addRequiredEdges(graph); meekOrient(graph, getKnowledge()); if (TetradLogger.getInstance().isEventActive("rebuiltPatterns")) { TetradLogger.getInstance().log("rebuiltPatterns", "Rebuilt pattern = " + graph); } }
public static boolean meekR1Locally2( Graph graph, Knowledge knowledge, IndependenceTest test, int depth) { List<Node> nodes = graph.getNodes(); boolean changed = true; while (changed) { changed = false; for (Node a : nodes) { List<Node> adjacentNodes = graph.getAdjacentNodes(a); if (adjacentNodes.size() < 2) { continue; } ChoiceGenerator cg = new ChoiceGenerator(adjacentNodes.size(), 2); int[] combination; while ((combination = cg.next()) != null) { Node b = adjacentNodes.get(combination[0]); Node c = adjacentNodes.get(combination[1]); // Skip triples that are shielded. if (graph.isAdjacentTo(b, c)) { continue; } if (graph.getEndpoint(b, a) == Endpoint.ARROW && graph.isUndirectedFromTo(a, c)) { if (existsLocalSepsetWithoutDet(b, a, c, test, graph, depth)) { continue; } if (isArrowpointAllowed(a, c, knowledge)) { graph.setEndpoint(a, c, Endpoint.ARROW); TetradLogger.getInstance() .edgeOriented(SearchLogUtils.edgeOrientedMsg("Meek R1", graph.getEdge(a, c))); changed = true; } } else if (graph.getEndpoint(c, a) == Endpoint.ARROW && graph.isUndirectedFromTo(a, b)) { if (existsLocalSepsetWithoutDet(b, a, c, test, graph, depth)) { continue; } if (isArrowpointAllowed(a, b, knowledge)) { graph.setEndpoint(a, b, Endpoint.ARROW); TetradLogger.getInstance() .edgeOriented(SearchLogUtils.edgeOrientedMsg("Meek R1", graph.getEdge(a, b))); changed = true; } } } } } return changed; }
/** * Performs step C of the algorithm, as indicated on page xxx of CPS, with the modification that * X--W--Y is oriented as X-->W<--Y if W is *determined by* the sepset of (X, Y), rather than W * just being *in* the sepset of (X, Y). */ public static void pcdOrientC( SepsetMap set, IndependenceTest test, Knowledge knowledge, Graph graph) { TetradLogger.getInstance().log("info", "Staring Collider Orientation:"); List<Node> nodes = graph.getNodes(); for (Node y : nodes) { List<Node> adjacentNodes = 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]); // Skip triples that are shielded. if (graph.isAdjacentTo(x, z)) { continue; } List<Node> sepset = set.get(x, z); if (sepset == null) { continue; } List<Node> augmentedSet = new LinkedList<Node>(sepset); augmentedSet.add(y); if (test.determines(sepset, y)) { continue; } // if (!test.splitDetermines(sepset, x, z) && test.splitDetermines(augmentedSet, x, z)) { continue; } if (!isArrowpointAllowed(x, y, knowledge) || !isArrowpointAllowed(z, y, knowledge)) { continue; } graph.setEndpoint(x, y, Endpoint.ARROW); graph.setEndpoint(z, y, Endpoint.ARROW); TetradLogger.getInstance() .log("colliderOriented", SearchLogUtils.colliderOrientedMsg(x, y, z)); } } TetradLogger.getInstance().log("info", "Finishing Collider Orientation."); }
public void configurationActived(TetradLoggerEvent evt) { TetradLoggerConfig config = evt.getTetradLoggerConfig(); // if logging is actually turned on, then open display. if (TetradLogger.getInstance().isLogging() && config.isActive() && TetradLogger.getInstance().isDisplayLogEnabled()) { // if the log display isn't already up, open it. if (!isDisplayLogging() && allowAutomaticLogPopup()) { setDisplayLogging(true); } } }
/** Orients according to background knowledge */ private void fciOrientbk(IKnowledge bk, Graph graph, List<Node> variables) { logger.log("info", "Starting BK Orientation."); for (Iterator<KnowledgeEdge> it = bk.forbiddenEdgesIterator(); it.hasNext(); ) { KnowledgeEdge edge = it.next(); // match strings to variables in the graph. Node from = SearchGraphUtils.translate(edge.getFrom(), variables); Node to = SearchGraphUtils.translate(edge.getTo(), variables); if (from == null || to == null) { continue; } if (graph.getEdge(from, to) == null) { continue; } // Orient to*->from graph.setEndpoint(to, from, Endpoint.ARROW); graph.setEndpoint(from, to, Endpoint.CIRCLE); changeFlag = true; logger.log( "knowledgeOrientation", SearchLogUtils.edgeOrientedMsg("Knowledge", graph.getEdge(from, to))); } for (Iterator<KnowledgeEdge> it = bk.requiredEdgesIterator(); it.hasNext(); ) { KnowledgeEdge edge = it.next(); // match strings to variables in this graph Node from = SearchGraphUtils.translate(edge.getFrom(), variables); Node to = SearchGraphUtils.translate(edge.getTo(), variables); if (from == null || to == null) { continue; } if (graph.getEdge(from, to) == null) { continue; } graph.setEndpoint(to, from, Endpoint.TAIL); graph.setEndpoint(from, to, Endpoint.ARROW); changeFlag = true; logger.log( "knowledgeOrientation", SearchLogUtils.edgeOrientedMsg("Knowledge", graph.getEdge(from, to))); } logger.log("info", "Finishing BK Orientation."); }
/** Orients according to background knowledge. */ public static void pcOrientbk(Knowledge bk, Graph graph, List<Node> nodes) { TetradLogger.getInstance().log("info", "Staring BK Orientation."); for (Iterator<KnowledgeEdge> it = bk.forbiddenEdgesIterator(); it.hasNext(); ) { KnowledgeEdge edge = it.next(); // match strings to variables in the graph. Node from = translate(edge.getFrom(), nodes); Node to = translate(edge.getTo(), nodes); if (from == null || to == null) { continue; } if (graph.getEdge(from, to) == null) { continue; } // Orient to-->from graph.removeEdge(from, to); graph.addDirectedEdge(from, to); graph.setEndpoint(from, to, Endpoint.TAIL); graph.setEndpoint(to, from, Endpoint.ARROW); TetradLogger.getInstance() .edgeOriented(SearchLogUtils.edgeOrientedMsg("Knowledge", graph.getEdge(to, from))); } for (Iterator<KnowledgeEdge> it = bk.requiredEdgesIterator(); it.hasNext(); ) { KnowledgeEdge edge = it.next(); // match strings to variables in this graph Node from = translate(edge.getFrom(), nodes); Node to = translate(edge.getTo(), nodes); if (from == null || to == null) { continue; } if (graph.getEdge(from, to) == null) { continue; } // Orient from-->to graph.setEndpoint(to, from, Endpoint.TAIL); graph.setEndpoint(from, to, Endpoint.ARROW); TetradLogger.getInstance() .edgeOriented(SearchLogUtils.edgeOrientedMsg("Knowledge", graph.getEdge(from, to))); } TetradLogger.getInstance().log("info", "Finishing BK Orientation."); }
private void ruleR1(Graph skeleton, Graph graph, List<Node> nodes) { for (Node node : nodes) { SortedMap<Double, String> scoreReports = new TreeMap<Double, String>(); List<Node> adj = skeleton.getAdjacentNodes(node); DepthChoiceGenerator gen = new DepthChoiceGenerator(adj.size(), adj.size()); int[] choice; double maxScore = Double.NEGATIVE_INFINITY; List<Node> parents = null; while ((choice = gen.next()) != null) { List<Node> _parents = GraphUtils.asList(choice, adj); double score = score(node, _parents); scoreReports.put(-score, _parents.toString()); if (score > maxScore) { maxScore = score; parents = _parents; } } for (double score : scoreReports.keySet()) { TetradLogger.getInstance() .log( "score", "For " + node + " parents = " + scoreReports.get(score) + " score = " + -score); } TetradLogger.getInstance().log("score", ""); if (parents == null) { continue; } if (normal(node, parents)) continue; for (Node _node : adj) { if (parents.contains(_node)) { Edge parentEdge = Edges.directedEdge(_node, node); if (!graph.containsEdge(parentEdge)) { graph.addEdge(parentEdge); } } } } }
private boolean isIndependentMultinomialLogisticRegression(Node x, Node y, List<Node> z) { double p = dependencePvalsLogit(x, y, z)[0]; boolean indep = p > alpha; // 0 corresponds to y this.lastP = p; if (indep) { TetradLogger.getInstance() .log("independencies", SearchLogUtils.independenceFactMsg(x, y, z, p)); } else { TetradLogger.getInstance().log("dependencies", SearchLogUtils.dependenceFactMsg(x, y, z, p)); } return indep; }
public static void orientUsingMeekRulesLocally2( Knowledge knowledge, Graph graph, IndependenceTest test, int depth) { TetradLogger.getInstance().log("info", "Starting Orientation Step D."); boolean changed; do { changed = meekR1Locally2(graph, knowledge, test, depth) || meekR2(graph, knowledge) || meekR3(graph, knowledge) || meekR4(graph, knowledge); } while (changed); TetradLogger.getInstance().log("info", "Finishing Orientation Step D."); }
private void log(String s, boolean toLog) { if (toLog) { TetradLogger.getInstance().log("info", s); } // System.out.println(s); }
private void bes(Graph graph) { TetradLogger.getInstance().log("info", "** BACKWARD EQUIVALENCE SEARCH"); initializeArrowsBackward(graph); while (!sortedArrows.isEmpty()) { Arrow arrow = sortedArrows.first(); sortedArrows.remove(arrow); Node x = arrow.getX(); Node y = arrow.getY(); clearArrow(x, y); if (!validDelete(arrow.getHOrT(), arrow.getNaYX(), graph)) { continue; } List<Node> h = arrow.getHOrT(); double bump = arrow.getBump(); delete(x, y, h, graph, bump); score += bump; rebuildPattern(graph); storeGraph(graph); initializeArrowsBackward( graph); // Rebuilds Arrows from scratch each time. Fast enough for backwards. } }
private boolean isIndependentRegression(Node x, Node y, List<Node> z) { double p = dependencePvalsLinear(x, y, z)[0]; // result.getP()[1]; this.lastP = p; boolean indep = p > alpha; if (verbose) { if (indep) { TetradLogger.getInstance() .log("independencies", SearchLogUtils.independenceFactMsg(x, y, z, p)); } else { TetradLogger.getInstance() .log("dependencies", SearchLogUtils.dependenceFactMsg(x, y, z, p)); } } return indep; }
/** * Searches for the Markov blanket of the node by the given name. * * @param targetName The name of the target node. * @return The Markov blanket of the target. */ public List<Node> findMb(String targetName) { TetradLogger.getInstance().log("info", "target = " + targetName); numIndTests = 0; long time = System.currentTimeMillis(); pc = new HashMap<>(); trimmed = new HashSet<>(); Node target = getVariableForName(targetName); List<Node> nodes = mmmb(target); long time2 = System.currentTimeMillis() - time; TetradLogger.getInstance().log("info", "Number of seconds: " + (time2 / 1000.0)); TetradLogger.getInstance() .log("info", "Number of independence tests performed: " + numIndTests); // System.out.println("Number of calls to mmpc = " + pc.size()); return nodes; }
/** Meek's rule R3. If a--b, a--c, a--d, c-->b, c-->b, then orient a-->b. */ public static boolean meekR3(Graph graph, Knowledge knowledge) { List<Node> nodes = graph.getNodes(); boolean changed = false; for (Node a : nodes) { List<Node> adjacentNodes = graph.getAdjacentNodes(a); if (adjacentNodes.size() < 3) { continue; } for (Node b : adjacentNodes) { List<Node> otherAdjacents = new LinkedList<Node>(adjacentNodes); otherAdjacents.remove(b); if (!graph.isUndirectedFromTo(a, b)) { continue; } ChoiceGenerator cg = new ChoiceGenerator(otherAdjacents.size(), 2); int[] combination; while ((combination = cg.next()) != null) { Node c = otherAdjacents.get(combination[0]); Node d = otherAdjacents.get(combination[1]); if (graph.isAdjacentTo(c, d)) { continue; } if (!graph.isUndirectedFromTo(a, c)) { continue; } if (!graph.isUndirectedFromTo(a, d)) { continue; } if (graph.isDirectedFromTo(c, b) && graph.isDirectedFromTo(d, b)) { if (isArrowpointAllowed(a, b, knowledge)) { graph.setEndpoint(a, b, Endpoint.ARROW); TetradLogger.getInstance() .edgeOriented(SearchLogUtils.edgeOrientedMsg("Meek R3", graph.getEdge(a, b))); changed = true; break; } } } } } return changed; }
/** * Step C of PC; orients colliders using specified sepset. That is, orients x *-* y *-* z as x *-> * y <-* z just in case y is in Sepset({x, z}). */ public static void orientCollidersUsingSepsets(SepsetMap set, Knowledge knowledge, Graph graph) { TetradLogger.getInstance().log("info", "Starting Collider Orientation:"); // verifySepsetIntegrity(set, graph); List<Node> nodes = graph.getNodes(); for (Node a : nodes) { List<Node> adjacentNodes = graph.getAdjacentNodes(a); if (adjacentNodes.size() < 2) { continue; } ChoiceGenerator cg = new ChoiceGenerator(adjacentNodes.size(), 2); int[] combination; while ((combination = cg.next()) != null) { Node b = adjacentNodes.get(combination[0]); Node c = adjacentNodes.get(combination[1]); // Skip triples that are shielded. if (graph.isAdjacentTo(b, c)) { continue; } List<Node> sepset = set.get(b, c); if (sepset != null && !sepset.contains(a) && isArrowpointAllowed(b, a, knowledge) && isArrowpointAllowed(c, a, knowledge)) { graph.setEndpoint(b, a, Endpoint.ARROW); graph.setEndpoint(c, a, Endpoint.ARROW); TetradLogger.getInstance() .log("colliderOriented", SearchLogUtils.colliderOrientedMsg(b, a, c, sepset)); } } } TetradLogger.getInstance().log("info", "Finishing Collider Orientation."); }
/** If */ public static boolean meekR2(Graph graph, Knowledge knowledge) { List<Node> nodes = graph.getNodes(); boolean changed = false; for (Node a : nodes) { List<Node> adjacentNodes = graph.getAdjacentNodes(a); if (adjacentNodes.size() < 2) { continue; } ChoiceGenerator cg = new ChoiceGenerator(adjacentNodes.size(), 2); int[] combination; while ((combination = cg.next()) != null) { Node b = adjacentNodes.get(combination[0]); Node c = adjacentNodes.get(combination[1]); if (graph.isDirectedFromTo(b, a) && graph.isDirectedFromTo(a, c) && graph.isUndirectedFromTo(b, c)) { if (isArrowpointAllowed(b, c, knowledge)) { graph.setEndpoint(b, c, Endpoint.ARROW); TetradLogger.getInstance() .edgeOriented(SearchLogUtils.edgeOrientedMsg("Meek R2", graph.getEdge(b, c))); } } else if (graph.isDirectedFromTo(c, a) && graph.isDirectedFromTo(a, b) && graph.isUndirectedFromTo(c, b)) { if (isArrowpointAllowed(c, b, knowledge)) { graph.setEndpoint(c, b, Endpoint.ARROW); TetradLogger.getInstance() .edgeOriented(SearchLogUtils.edgeOrientedMsg("Meek R2", graph.getEdge(c, b))); } } } } return changed; }
public static void orientCollidersLocally( Knowledge knowledge, Graph graph, IndependenceTest test, int depth, Set<Node> nodesToVisit) { TetradLogger.getInstance().log("info", "Starting Collider Orientation:"); if (nodesToVisit == null) { nodesToVisit = new HashSet<Node>(graph.getNodes()); } for (Node a : nodesToVisit) { List<Node> adjacentNodes = graph.getAdjacentNodes(a); if (adjacentNodes.size() < 2) { continue; } ChoiceGenerator cg = new ChoiceGenerator(adjacentNodes.size(), 2); int[] combination; while ((combination = cg.next()) != null) { Node b = adjacentNodes.get(combination[0]); Node c = adjacentNodes.get(combination[1]); // Skip triples that are shielded. if (graph.isAdjacentTo(b, c)) { continue; } if (isArrowpointAllowed1(b, a, knowledge) && isArrowpointAllowed1(c, a, knowledge)) { if (!existsLocalSepsetWith(b, a, c, test, graph, depth)) { graph.setEndpoint(b, a, Endpoint.ARROW); graph.setEndpoint(c, a, Endpoint.ARROW); TetradLogger.getInstance() .log("colliderOriented", SearchLogUtils.colliderOrientedMsg(b, a, c)); } } } } TetradLogger.getInstance().log("info", "Finishing Collider Orientation."); }
/** * Sets whether the display log output should be displayed or not. If true then a text area * roughly 20% of the screen size will appear on the bottom and will display any log output, * otherwise just the standard tetrad workbend is shown. * * @param displayLogging */ public void setDisplayLogging(boolean displayLogging) { if (displayLogging) { this.logArea = new TetradLogArea(this); } else { if (this.logArea != null) { TetradLogger.getInstance().removeOutputStream(this.logArea.getOutputStream()); } this.logArea = null; } setupDesktop(); revalidate(); repaint(); }
/** * States whether the log display should be automatically displayed, if there is no value in the * user's prefs then it will display a prompt asking the user whether they would like to disable * automatic popups. */ private boolean allowAutomaticLogPopup() { Boolean allowed = TetradLogger.getInstance().isAutomaticLogDisplayEnabled(); // ask the user whether they way the feature etc. if (allowed == null) { String message = "<html>Whenever Tetrad's logging features are active any generated log <br>" + "output will be automatically display in Tetrad's log display. Would you like Tetrad<br>" + "to continue to automatically open the log display window whenever there is logging output?</html>"; int option = JOptionPane.showConfirmDialog( this, message, "Automatic Logging", JOptionPane.YES_NO_OPTION); if (option == JOptionPane.NO_OPTION) { JOptionPane.showMessageDialog( this, "This feature can be enabled later by going to Logging>Setup Logging."); } TetradLogger.getInstance().setAutomaticLogDisplayEnabled(option == JOptionPane.YES_OPTION); // return true, so that opens this time, in the future the user's pref will be used. return true; } return allowed; }
public Graph search(IFas fas, List<Node> nodes) { long beginTime = System.currentTimeMillis(); logger.log("info", "Starting FCI algorithm."); logger.log("info", "Independence test = " + getIndependenceTest() + "."); setMaxPathLength(maxPathLength); this.graph = new EdgeListGraph(nodes); long start1 = System.currentTimeMillis(); fas.setKnowledge(getKnowledge()); fas.setDepth(depth); fas.setVerbose(verbose); // fas.setFci(true); graph = fas.search(); graph.reorientAllWith(Endpoint.CIRCLE); this.sepsets = fas.getSepsets(); long stop1 = System.currentTimeMillis(); long start2 = System.currentTimeMillis(); // The original FCI, with or without JiJi Zhang's orientation rules fciOrientbk(getKnowledge(), graph, variables); ruleR0_RFCI(getRTuples()); // RFCI Algorithm 4.4 doFinalOrientation(); long endTime = System.currentTimeMillis(); this.elapsedTime = endTime - beginTime; logger.log("graph", "Returning graph: " + graph); long stop2 = System.currentTimeMillis(); logger.log("info", "Elapsed time adjacency search = " + (stop1 - start1) / 1000L + "s"); logger.log("info", "Elapsed time orientation search = " + (stop2 - start2) / 1000L + "s"); return graph; }
/** Constructs a new desktop. */ public TetradDesktop() { setBackground(new Color(204, 204, 204)); sessionNodeKeys = new ArrayList(); // Create the desktop pane. this.desktopPane = new JDesktopPane(); // Do layout. setLayout(new BorderLayout()); desktopPane.setDesktopManager(new DefaultDesktopManager()); desktopPane.setBorder(new BevelBorder(BevelBorder.LOWERED)); desktopPane.addPropertyChangeListener(this); this.setupDesktop(); TetradLogger.getInstance().addTetradLoggerListener(new LoggerListener()); }
/** * Forward equivalence search. * * @param graph The graph in the state prior to the forward equivalence search. */ private void fes(Graph graph, List<Node> nodes) { TetradLogger.getInstance().log("info", "** FORWARD EQUIVALENCE SEARCH"); lookupArrows = new HashMap<OrderedPair, Set<Arrow>>(); initializeArrowsForward(nodes); while (!sortedArrows.isEmpty()) { Arrow arrow = sortedArrows.first(); sortedArrows.remove(arrow); Node x = arrow.getX(); Node y = arrow.getY(); clearArrow(x, y); if (graph.isAdjacentTo(x, y)) { continue; } if (!validInsert(x, y, arrow.getHOrT(), arrow.getNaYX(), graph)) { continue; } List<Node> t = arrow.getHOrT(); double bump = arrow.getBump(); Set<Edge> edges = graph.getEdges(); insert(x, y, t, graph, bump); score += bump; rebuildPattern(graph); // Try to avoid duplicating scoring calls. First clear out all of the edges that need to be // changed, // then change them, checking to see if they're already been changed. I know, roundabout, but // there's // a performance boost. for (Edge edge : graph.getEdges()) { if (!edges.contains(edge)) { reevaluateForward(graph, nodes, edge.getNode1(), edge.getNode2()); } } storeGraph(graph); } }
/** @return the p value for the most recent test. */ @Override public double getPValue() { double cdf = ProbUtils.chisqCdf(this.chisq, this.df); double p = 1.0 - cdf; String s = ""; for (int i = 0; i < storedSextads.length; i++) { s += storedSextads[i] + " "; } s += "value = " + nf.format(storedValue) + " p = " + nf.format(p); TetradLogger.getInstance().log("sextadPValues", s); return p; }
public static boolean existsLocalSepsetWithoutDet( Node x, Node y, Node z, IndependenceTest test, Graph graph, int depth) { Set<Node> __nodes = new HashSet<Node>(graph.getAdjacentNodes(x)); __nodes.addAll(graph.getAdjacentNodes(z)); __nodes.remove(x); __nodes.remove(z); List<Node> _nodes = new LinkedList<Node>(__nodes); TetradLogger.getInstance() .log("adjacencies", "Adjacents for " + x + "--" + y + "--" + z + " = " + _nodes); int _depth = depth; if (_depth == -1) { _depth = 1000; } _depth = Math.min(_depth, _nodes.size()); for (int d = 0; d <= _depth; d++) { if (_nodes.size() >= d) { ChoiceGenerator cg2 = new ChoiceGenerator(_nodes.size(), d); int[] choice; while ((choice = cg2.next()) != null) { List<Node> condSet = asList(choice, _nodes); if (condSet.contains(y)) { continue; } if (test.determines(condSet, y)) { continue; } // LogUtils.getInstance().finest("Trying " + condSet); if (test.isIndependent(x, z, condSet)) { return true; } } } } return false; }
private List<Node> mmpc(Node t) { List<Node> pc = new LinkedList<>(); boolean pcIncreased = true; // First optimization: Don't consider adding again variables that have // already been found independent of t. List<Node> indepOfT = new LinkedList<>(); // Phase 1 while (pcIncreased) { pcIncreased = false; MaxMinAssocResult ret = maxMinAssoc(t, pc, indepOfT); Node f = ret.getNode(); List<Node> assocSet = ret.getAssocSet(); if (f == null) { break; } numIndTests++; if (!independenceTest.isIndependent(f, t, assocSet)) { pcIncreased = true; pc.add(f); } } // Phase 2. backwardsConditioning(pc, t); TetradLogger.getInstance().log("details", "PC(" + t + ") = " + pc); // System.out.println("PC(" + t + ") = " + pc); return pc; }
private void log(BayesIm im) { TetradLogger.getInstance().log("info", "Maximum likelihood Bayes IM: Observed Variables Only"); TetradLogger.getInstance().log("im", im.toString()); }
private void log(BayesIm im) { TetradLogger.getInstance().log("info", "Maximum likelihood Bayes IM"); TetradLogger.getInstance().log("im", im.toString()); }
/** * Implements the PC ("Peter/Clark") algorithm, as specified in Chapter 6 of Spirtes, Glymour, and * Scheines, "Causation, Prediction, and Search," 2nd edition, with a modified rule set in step D * due to Chris Meek. For the modified rule set, see Chris Meek (1995), "Causal inference and causal * explanation with background knowledge." * * <p>In addition, the PC Stable modification to PC has been included (Colombo and Maathuis). * * @author Joseph Ramsey. */ public class PcStable implements GraphSearch { /** The independence test used for the PC search. */ private IndependenceTest independenceTest; /** Forbidden and required edges for the search. */ private IKnowledge knowledge = new Knowledge(); /** Sepset information accumulated in the search. */ private SepsetMap sepsets; /** The maximum number of nodes conditioned on in the search. The default it 1000. */ private int depth = 1000; /** The graph that's constructed during the search. */ private Graph graph; /** Elapsed time of the most recent search. */ private long elapsedTime; /** * True if cycles are to be aggressively prevented. May be expensive for large graphs (but also * useful for large graphs). */ private boolean aggressivelyPreventCycles = false; /** The logger for this class. The config needs to be set. */ private TetradLogger logger = TetradLogger.getInstance(); /** The initial graph for the Fast Adjacency Search, or null if there is none. */ private Graph initialGraph = null; /** Prints independencies info to out. */ private boolean verbose = false; private PrintStream out = System.out; // =============================CONSTRUCTORS==========================// /** * Constructs a new PC search using the given independence test as oracle. * * @param independenceTest The oracle for conditional independence facts. This does not make a * copy of the independence test, for fear of duplicating the data set! */ public PcStable(IndependenceTest independenceTest) { if (independenceTest == null) { throw new NullPointerException(); } this.independenceTest = independenceTest; } // ==============================PUBLIC METHODS========================// /** @return true iff edges will not be added if they would create cycles. */ public boolean isAggressivelyPreventCycles() { return this.aggressivelyPreventCycles; } /** * @param aggressivelyPreventCycles Set to true just in case edges will not be addeds if they * would create cycles. */ public void setAggressivelyPreventCycles(boolean aggressivelyPreventCycles) { this.aggressivelyPreventCycles = aggressivelyPreventCycles; } /** @return the independence test being used in the search. */ public IndependenceTest getIndependenceTest() { return independenceTest; } /** @return the knowledge specification used in the search. Non-null. */ public IKnowledge getKnowledge() { return knowledge; } /** Sets the knowledge specification to be used in the search. May not be null. */ public void setKnowledge(IKnowledge knowledge) { if (knowledge == null) { throw new NullPointerException(); } this.knowledge = knowledge; } /** * @return the sepset map from the most recent search. Non-null after the first call to <code> * search()</code>. */ public SepsetMap getSepsets() { return this.sepsets; } /** * @return the current depth of search--that is, the maximum number of conditioning nodes for any * conditional independence checked. */ public int getDepth() { return depth; } /** * Sets the depth of the search--that is, the maximum number of conditioning nodes for any * conditional independence checked. * * @param depth The depth of the search. The default is 1000. A value of -1 may be used to * indicate that the depth should be high (1000). A value of Integer.MAX_VALUE may not be * used, due to a bug on multi-core machines. */ public void setDepth(int depth) { if (depth < -1) { throw new IllegalArgumentException("Depth must be -1 or >= 0: " + depth); } if (depth > 1000) { throw new IllegalArgumentException("Depth must be <= 1000."); } this.depth = depth; } /** * Runs PC starting with a complete graph over all nodes of the given conditional independence * test, using the given independence test and knowledge and returns the resultant graph. The * returned graph will be a pattern if the independence information is consistent with the * hypothesis that there are no latent common causes. It may, however, contain cycles or * bidirected edges if this assumption is not born out, either due to the actual presence of * latent common causes, or due to statistical errors in conditional independence judgments. */ public Graph search() { return search(independenceTest.getVariables()); } /** * Runs PC starting with a commplete graph over the given list of nodes, using the given * independence test and knowledge and returns the resultant graph. The returned graph will be a * pattern if the independence information is consistent with the hypothesis that there are no * latent common causes. It may, however, contain cycles or bidirected edges if this assumption is * not born out, either due to the actual presence of latent common causes, or due to statistical * errors in conditional independence judgments. * * <p>All of the given nodes must be in the domain of the given conditional independence test. */ public Graph search(List<Node> nodes) { this.logger.log("info", "Starting PC algorithm"); this.logger.log("info", "Independence test = " + getIndependenceTest() + "."); // this.logger.log("info", "Variables " + independenceTest.getVariables()); long startTime = System.currentTimeMillis(); if (getIndependenceTest() == null) { throw new NullPointerException(); } List allNodes = getIndependenceTest().getVariables(); if (!allNodes.containsAll(nodes)) { throw new IllegalArgumentException( "All of the given nodes must " + "be in the domain of the independence test provided."); } graph = new EdgeListGraph(nodes); IFas fas = new FasStableConcurrent(initialGraph, getIndependenceTest()); fas.setKnowledge(getKnowledge()); fas.setDepth(getDepth()); fas.setVerbose(verbose); graph = fas.search(); sepsets = fas.getSepsets(); SearchGraphUtils.pcOrientbk(knowledge, graph, nodes); // SearchGraphUtils.orientCollidersUsingSepsets(this.sepsets, knowledge, graph, // initialGraph, verbose); // SearchGraphUtils.orientCollidersUsingSepsets(this.sepsets, knowledge, graph, verbose); // SearchGraphUtils.orientColeelidersLocally(knowledge, graph, independenceTest, depth); SearchGraphUtils.orientCollidersUsingSepsets(this.sepsets, knowledge, graph, verbose); MeekRules rules = new MeekRules(); rules.setAggressivelyPreventCycles(this.aggressivelyPreventCycles); rules.setKnowledge(knowledge); rules.orientImplied(graph); this.logger.log("graph", "\nReturning this graph: " + graph); this.elapsedTime = System.currentTimeMillis() - startTime; this.logger.log("info", "Elapsed time = " + (elapsedTime) / 1000. + " s"); this.logger.log("info", "Finishing PC Algorithm."); this.logger.flush(); return graph; } /** @return the elapsed time of the search, in milliseconds. */ public long getElapsedTime() { return elapsedTime; } // ===============================PRIVATE METHODS=======================// public List<Node> getNodes() { return graph.getNodes(); } public void setInitialGraph(Graph initialGraph) { this.initialGraph = initialGraph; } public void setVerbose(boolean verbose) { this.verbose = verbose; } public void setOut(PrintStream out) { this.out = out; } public PrintStream getOut() { return out; } }