/** * 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."); }
/** * Double checks a sepset map against a pattern to make sure that X is adjacent to Y in the * pattern iff {X, Y} is not in the domain of the sepset map. * * @param sepset a sepset map, over variables V. * @param pattern a pattern over variables W, V subset of W. * @return true if the sepset map is consistent with the pattern. */ public static boolean verifySepsetIntegrity(SepsetMap sepset, Graph pattern) { for (Node x : pattern.getNodes()) { for (Node y : pattern.getNodes()) { if (x == y) { continue; } if ((pattern.isAdjacentTo(y, x)) != (sepset.get(x, y) == null)) { System.out.println("Sepset not consistent with graph for {" + x + ", " + y + "}"); return false; } } } return true; }
/** * 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."); }