//////////////////////////////////////////////// // collect in rTupleList all unshielded tuples //////////////////////////////////////////////// private List<Node[]> getRTuples() { List<Node[]> rTuples = new ArrayList<Node[]>(); List<Node> nodes = graph.getNodes(); for (Node j : nodes) { List<Node> adjacentNodes = graph.getAdjacentNodes(j); if (adjacentNodes.size() < 2) { continue; } ChoiceGenerator cg = new ChoiceGenerator(adjacentNodes.size(), 2); int[] combination; while ((combination = cg.next()) != null) { Node i = adjacentNodes.get(combination[0]); Node k = adjacentNodes.get(combination[1]); // Skip triples that are shielded. if (!graph.isAdjacentTo(i, k)) { Node[] newTuple = {i, j, k}; rTuples.add(newTuple); } } } return (rTuples); }
private boolean existsUnblockedSemiDirectedPath(Node from, Node to, List<Node> cond, Graph G) { Queue<Node> Q = new LinkedList<Node>(); Set<Node> V = new HashSet<Node>(); Q.offer(from); V.add(from); while (!Q.isEmpty()) { Node t = Q.remove(); if (t == to) return true; for (Node u : G.getAdjacentNodes(t)) { Edge edge = G.getEdge(t, u); Node c = Edges.traverseSemiDirected(t, edge); if (c == null) continue; if (cond.contains(c)) continue; if (c == to) return true; if (!V.contains(c)) { V.add(c); Q.offer(c); } } } return false; }
public List<Triple> getUnshieldedCollidersFromGraph(Graph graph) { List<Triple> colliders = new ArrayList<>(); 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; } if (graph.isDefCollider(a, b, c)) { colliders.add(new Triple(a, b, c)); } } } return colliders; }
private static int shortestPath(Node n1, Node n2, Graph g) { Queue<Node> Q = new ArrayDeque<Node>(); Map<Node, Node> V = new HashMap<Node, Node>(); Q.offer(n1); V.put(n1, null); while (!Q.isEmpty()) { Node m = Q.poll(); if (V.containsKey(n2)) break; for (Node p : g.getAdjacentNodes(m)) { if (V.containsKey(p)) continue; Q.offer(p); V.put(p, m); } } int s = 0; do { s++; n2 = V.get(n2); } while (n2 != null); return s; }
/** * 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; }
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."); }
/** * Returns the set of nodes reachable from the given set of initial nodes in the given graph * according to the criteria in the given legal pairs object. * * <p>A variable V is reachable from initialNodes iff for some variable X in initialNodes thers is * a path U [X, Y1, ..., V] such that legalPairs.isLegalFirstNode(X, Y1) and for each [H1, H2, H3] * as subpaths of U, legalPairs.isLegalPairs(H1, H2, H3). * * <p>The algorithm used is a variant of Algorithm 1 from Geiger, Verma, & Pearl (1990). * * @param initialNodes The nodes that reachability paths start from. * @param legalPairs Specifies initial edges (given initial nodes) and legal edge pairs. * @param c a set of vertices (intuitively, the set of variables to be conditioned on. * @param d a set of vertices (intuitively to be used in tests of legality, for example, the set * of ancestors of c). * @param graph the graph with respect to which reachability is determined. */ public static Set<Node> getReachableNodes( List<Node> initialNodes, LegalPairs legalPairs, List<Node> c, List<Node> d, Graph graph) { HashSet<Node> reachable = new HashSet<Node>(); MultiKeyMap visited = new MultiKeyMap(); List<ReachabilityEdge> nextEdges = new LinkedList<ReachabilityEdge>(); for (Node x : initialNodes) { List<Node> adjX = graph.getAdjacentNodes(x); for (Node y : adjX) { if (legalPairs.isLegalFirstEdge(x, y)) { reachable.add(y); nextEdges.add(new ReachabilityEdge(x, y)); visited.put(x, y, Boolean.TRUE); } } } while (nextEdges.size() > 0) { List<ReachabilityEdge> currEdges = nextEdges; nextEdges = new LinkedList<ReachabilityEdge>(); for (ReachabilityEdge edge : currEdges) { Node x = edge.getFrom(); Node y = edge.getTo(); List<Node> adjY = graph.getAdjacentNodes(y); for (Node z : adjY) { if ((visited.get(y, z)) == Boolean.TRUE) { continue; } if (legalPairs.isLegalPair(x, y, z, c, d)) { reachable.add(z); nextEdges.add(new ReachabilityEdge(y, z)); visited.put(y, z, Boolean.TRUE); } } } } return reachable; }
private boolean localMarkovIndep(Node x, Node y, Graph pattern, IndependenceTest test) { List<Node> future = pattern.getDescendants(Collections.singletonList(x)); List<Node> boundary = pattern.getAdjacentNodes(x); boundary.removeAll(future); List<Node> closure = new ArrayList<>(boundary); closure.add(x); closure.remove(y); if (future.contains(y) || boundary.contains(y)) return false; return test.isIndependent(x, y, boundary); }
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; }
/** 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; }
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); } } } } }
/** * 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."); }
//////////////////////////////////////////// // RFCI Algorithm 4.4 (Colombo et al, 2012) // Orient colliders //////////////////////////////////////////// private void ruleR0_RFCI(List<Node[]> rTuples) { List<Node[]> lTuples = new ArrayList<Node[]>(); List<Node> nodes = graph.getNodes(); /////////////////////////////// // process tuples in rTuples while (!rTuples.isEmpty()) { Node[] thisTuple = rTuples.remove(0); Node i = thisTuple[0]; Node j = thisTuple[1]; Node k = thisTuple[2]; final List<Node> nodes1 = getSepset(i, k); if (nodes1 == null) continue; List<Node> sepSet = new ArrayList<Node>(nodes1); sepSet.remove(j); boolean independent1 = false; if (knowledge.noEdgeRequired(i.getName(), j.getName())) // if BK allows { try { independent1 = independenceTest.isIndependent(i, j, sepSet); } catch (Exception e) { independent1 = true; } } boolean independent2 = false; if (knowledge.noEdgeRequired(j.getName(), k.getName())) // if BK allows { try { independent2 = independenceTest.isIndependent(j, k, sepSet); } catch (Exception e) { independent2 = true; } } if (!independent1 && !independent2) { lTuples.add(thisTuple); } else { // set sepSets to minimal separating sets if (independent1) { setMinSepSet(sepSet, i, j); graph.removeEdge(i, j); } if (independent2) { setMinSepSet(sepSet, j, k); graph.removeEdge(j, k); } // add new unshielded tuples to rTuples for (Node thisNode : nodes) { List<Node> adjacentNodes = graph.getAdjacentNodes(thisNode); if (independent1) // <i, ., j> { if (adjacentNodes.contains(i) && adjacentNodes.contains(j)) { Node[] newTuple = {i, thisNode, j}; rTuples.add(newTuple); } } if (independent2) // <j, ., k> { if (adjacentNodes.contains(j) && adjacentNodes.contains(k)) { Node[] newTuple = {j, thisNode, k}; rTuples.add(newTuple); } } } // remove tuples involving either (if independent1) <i, j> // or (if independent2) <j, k> from rTuples Iterator<Node[]> iter = rTuples.iterator(); while (iter.hasNext()) { Node[] curTuple = iter.next(); if ((independent1 && (curTuple[1] == i) && ((curTuple[0] == j) || (curTuple[2] == j))) || (independent2 && (curTuple[1] == k) && ((curTuple[0] == j) || (curTuple[2] == j))) || (independent1 && (curTuple[1] == j) && ((curTuple[0] == i) || (curTuple[2] == i))) || (independent2 && (curTuple[1] == j) && ((curTuple[0] == k) || (curTuple[2] == k)))) { iter.remove(); } } // remove tuples involving either (if independent1) <i, j> // or (if independent2) <j, k> from lTuples iter = lTuples.iterator(); while (iter.hasNext()) { Node[] curTuple = iter.next(); if ((independent1 && (curTuple[1] == i) && ((curTuple[0] == j) || (curTuple[2] == j))) || (independent2 && (curTuple[1] == k) && ((curTuple[0] == j) || (curTuple[2] == j))) || (independent1 && (curTuple[1] == j) && ((curTuple[0] == i) || (curTuple[2] == i))) || (independent2 && (curTuple[1] == j) && ((curTuple[0] == k) || (curTuple[2] == k)))) { iter.remove(); } } } } /////////////////////////////////////////////////////// // orient colliders (similar to original FCI ruleR0) for (Node[] thisTuple : lTuples) { Node i = thisTuple[0]; Node j = thisTuple[1]; Node k = thisTuple[2]; List<Node> sepset = getSepset(i, k); if (sepset == null) { continue; } if (!sepset.contains(j) && graph.isAdjacentTo(i, j) && graph.isAdjacentTo(j, k)) { if (!isArrowpointAllowed(i, j)) { continue; } if (!isArrowpointAllowed(k, j)) { continue; } graph.setEndpoint(i, j, Endpoint.ARROW); graph.setEndpoint(k, j, Endpoint.ARROW); printWrongColliderMessage(i, j, k, "R0_RFCI"); } } }
public static CpcTripleType getCpcTripleType( Node x, Node y, Node z, IndependenceTest test, int depth, Graph graph) { // System.out.println("getCpcTripleType 1"); boolean existsSepsetContainingY = false; boolean existsSepsetNotContainingY = false; Set<Node> __nodes = new HashSet<Node>(graph.getAdjacentNodes(x)); __nodes.remove(z); // System.out.println("getCpcTripleType 2"); List<Node> _nodes = new LinkedList<Node>(__nodes); TetradLogger.getInstance() .log("adjacencies", "Adjacents for " + x + "--" + y + "--" + z + " = " + _nodes); // System.out.println("getCpcTripleType 3"); int _depth = depth; if (_depth == -1) { _depth = 1000; } _depth = Math.min(_depth, _nodes.size()); // System.out.println("getCpcTripleType 4"); for (int d = 0; d <= _depth; d++) { // System.out.println("getCpcTripleType 5"); ChoiceGenerator cg = new ChoiceGenerator(_nodes.size(), d); int[] choice; while ((choice = cg.next()) != null) { // System.out.println("getCpcTripleType 6"); List<Node> condSet = GraphUtils.asList(choice, _nodes); // System.out.println("getCpcTripleType 7"); if (test.isIndependent(x, z, condSet)) { if (condSet.contains(y)) { existsSepsetContainingY = true; } else { existsSepsetNotContainingY = true; } } } } // System.out.println("getCpcTripleType 8"); __nodes = new HashSet<Node>(graph.getAdjacentNodes(z)); __nodes.remove(x); _nodes = new LinkedList<Node>(__nodes); TetradLogger.getInstance() .log("adjacencies", "Adjacents for " + x + "--" + y + "--" + z + " = " + _nodes); // System.out.println("getCpcTripleType 9"); _depth = depth; if (_depth == -1) { _depth = 1000; } _depth = Math.min(_depth, _nodes.size()); // System.out.println("getCpcTripleType 10"); for (int d = 0; d <= _depth; d++) { // System.out.println("getCpcTripleType 11"); ChoiceGenerator cg = new ChoiceGenerator(_nodes.size(), d); int[] choice; while ((choice = cg.next()) != null) { List<Node> condSet = GraphUtils.asList(choice, _nodes); if (test.isIndependent(x, z, condSet)) { if (condSet.contains(y)) { existsSepsetContainingY = true; } else { existsSepsetNotContainingY = true; } } } } // System.out.println("getCpcTripleType 12"); if (existsSepsetContainingY == existsSepsetNotContainingY) { return CpcTripleType.AMBIGUOUS; } else if (!existsSepsetNotContainingY) { return CpcTripleType.NONCOLLIDER; } else { return CpcTripleType.COLLIDER; } }
private void resolveOneEdgeMax(Graph graph, Node x, Node y, boolean strong, Graph oldGraph) { if (RandomUtil.getInstance().nextDouble() > 0.5) { Node temp = x; x = y; y = temp; } TetradLogger.getInstance().log("info", "\nEDGE " + x + " --- " + y); SortedMap<Double, String> scoreReports = new TreeMap<Double, String>(); List<Node> neighborsx = graph.getAdjacentNodes(x); neighborsx.remove(y); double max = Double.NEGATIVE_INFINITY; boolean left = false; boolean right = false; DepthChoiceGenerator genx = new DepthChoiceGenerator(neighborsx.size(), neighborsx.size()); int[] choicex; while ((choicex = genx.next()) != null) { List<Node> condxMinus = GraphUtils.asList(choicex, neighborsx); List<Node> condxPlus = new ArrayList<Node>(condxMinus); condxPlus.add(y); double xPlus = score(x, condxPlus); double xMinus = score(x, condxMinus); List<Node> neighborsy = graph.getAdjacentNodes(y); neighborsy.remove(x); DepthChoiceGenerator geny = new DepthChoiceGenerator(neighborsy.size(), neighborsy.size()); int[] choicey; while ((choicey = geny.next()) != null) { List<Node> condyMinus = GraphUtils.asList(choicey, neighborsy); // List<Node> parentsY = oldGraph.getParents(y); // parentsY.remove(x); // if (!condyMinus.containsAll(parentsY)) { // continue; // } List<Node> condyPlus = new ArrayList<Node>(condyMinus); condyPlus.add(x); double yPlus = score(y, condyPlus); double yMinus = score(y, condyMinus); // Checking them all at once is expensive but avoids lexical ordering problems in the // algorithm. if (normal(y, condyPlus) || normal(x, condxMinus) || normal(x, condxPlus) || normal(y, condyMinus)) { continue; } double delta = 0.0; if (strong) { if (yPlus <= xPlus + delta && xMinus <= yMinus + delta) { double score = combinedScore(xPlus, yMinus); if (yPlus <= yMinus + delta && xMinus <= xPlus + delta) { StringBuilder builder = new StringBuilder(); builder.append("\nStrong " + y + "->" + x + " " + score); builder.append("\n Parents(" + x + ") = " + condxMinus); builder.append("\n Parents(" + y + ") = " + condyMinus); scoreReports.put(-score, builder.toString()); if (score > max) { max = score; left = true; right = false; } } else { StringBuilder builder = new StringBuilder(); builder.append("\nNo directed edge " + x + "--" + y + " " + score); builder.append("\n Parents(" + x + ") = " + condxMinus); builder.append("\n Parents(" + y + ") = " + condyMinus); scoreReports.put(-score, builder.toString()); } } else if (xPlus <= yPlus + delta && yMinus <= xMinus + delta) { double score = combinedScore(yPlus, xMinus); if (yMinus <= yPlus + delta && xPlus <= xMinus + delta) { StringBuilder builder = new StringBuilder(); builder.append("\nStrong " + x + "->" + y + " " + score); builder.append("\n Parents(" + x + ") = " + condxMinus); builder.append("\n Parents(" + y + ") = " + condyMinus); scoreReports.put(-score, builder.toString()); if (score > max) { max = score; left = false; right = true; } } else { StringBuilder builder = new StringBuilder(); builder.append("\nNo directed edge " + x + "--" + y + " " + score); builder.append("\n Parents(" + x + ") = " + condxMinus); builder.append("\n Parents(" + y + ") = " + condyMinus); scoreReports.put(-score, builder.toString()); } } else if (yPlus <= xPlus + delta && yMinus <= xMinus + delta) { double score = combinedScore(yPlus, xMinus); StringBuilder builder = new StringBuilder(); builder.append("\nNo directed edge " + x + "--" + y + " " + score); builder.append("\n Parents(" + x + ") = " + condxMinus); builder.append("\n Parents(" + y + ") = " + condyMinus); scoreReports.put(-score, builder.toString()); } else if (xPlus <= yPlus + delta && xMinus <= yMinus + delta) { double score = combinedScore(yPlus, xMinus); StringBuilder builder = new StringBuilder(); builder.append("\nNo directed edge " + x + "--" + y + " " + score); builder.append("\n Parents(" + x + ") = " + condxMinus); builder.append("\n Parents(" + y + ") = " + condyMinus); scoreReports.put(-score, builder.toString()); } } else { if (yPlus <= xPlus + delta && xMinus <= yMinus + delta) { double score = combinedScore(xPlus, yMinus); StringBuilder builder = new StringBuilder(); builder.append("\nWeak " + y + "->" + x + " " + score); builder.append("\n Parents(" + x + ") = " + condxMinus); builder.append("\n Parents(" + y + ") = " + condyMinus); scoreReports.put(-score, builder.toString()); if (score > max) { max = score; left = true; right = false; } } else if (xPlus <= yPlus + delta && yMinus <= xMinus + delta) { double score = combinedScore(yPlus, xMinus); StringBuilder builder = new StringBuilder(); builder.append("\nWeak " + x + "->" + y + " " + score); builder.append("\n Parents(" + x + ") = " + condxMinus); builder.append("\n Parents(" + y + ") = " + condyMinus); scoreReports.put(-score, builder.toString()); if (score > max) { max = score; left = false; right = true; } } else if (yPlus <= xPlus + delta && yMinus <= xMinus + delta) { double score = combinedScore(yPlus, xMinus); StringBuilder builder = new StringBuilder(); builder.append("\nNo directed edge " + x + "--" + y + " " + score); builder.append("\n Parents(" + x + ") = " + condxMinus); builder.append("\n Parents(" + y + ") = " + condyMinus); scoreReports.put(-score, builder.toString()); } else if (xPlus <= yPlus + delta && xMinus <= yMinus + delta) { double score = combinedScore(yPlus, xMinus); StringBuilder builder = new StringBuilder(); builder.append("\nNo directed edge " + x + "--" + y + " " + score); builder.append("\n Parents(" + x + ") = " + condxMinus); builder.append("\n Parents(" + y + ") = " + condyMinus); scoreReports.put(-score, builder.toString()); } } } } for (double score : scoreReports.keySet()) { TetradLogger.getInstance().log("info", scoreReports.get(score)); } graph.removeEdges(x, y); if (left) { graph.addDirectedEdge(y, x); } if (right) { graph.addDirectedEdge(x, y); } if (!graph.isAdjacentTo(x, y)) { graph.addUndirectedEdge(x, y); } }