///////////////////////////////////////////////////////////////////////////// // set the sepSet of x and y to the minimal such subset of the given sepSet // and remove the edge <x, y> if background knowledge allows ///////////////////////////////////////////////////////////////////////////// private void setMinSepSet(List<Node> sepSet, Node x, Node y) { // It is assumed that BK has been considered before calling this method // (for example, setting independent1 and independent2 in ruleR0_RFCI) /* // background knowledge requires this edge if (knowledge.noEdgeRequired(x.getNode(), y.getNode())) { return; } */ List<Node> empty = Collections.emptyList(); boolean indep; try { indep = independenceTest.isIndependent(x, y, empty); } catch (Exception e) { indep = false; } if (indep) { getSepsets().set(x, y, empty); return; } int sepSetSize = sepSet.size(); for (int i = 1; i <= sepSetSize; i++) { ChoiceGenerator cg = new ChoiceGenerator(sepSetSize, i); int[] combination; while ((combination = cg.next()) != null) { List<Node> condSet = GraphUtils.asList(combination, sepSet); try { indep = independenceTest.isIndependent(x, y, condSet); } catch (Exception e) { indep = false; } if (indep) { getSepsets().set(x, y, condSet); return; } } } }
/** Constructs a new FCI search for the given independence test and background knowledge. */ public Rfci(IndependenceTest independenceTest) { if (independenceTest == null || knowledge == null) { throw new NullPointerException(); } this.independenceTest = independenceTest; this.variables.addAll(independenceTest.getVariables()); }
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); }
/** * Constructs a new FCI search for the given independence test and background knowledge and a list * of variables to search over. */ public Rfci(IndependenceTest independenceTest, List<Node> searchVars) { if (independenceTest == null || knowledge == null) { throw new NullPointerException(); } this.independenceTest = independenceTest; this.variables.addAll(independenceTest.getVariables()); Set<Node> remVars = new HashSet<Node>(); for (Node node1 : this.variables) { boolean search = false; for (Node node2 : searchVars) { if (node1.getName().equals(node2.getName())) { search = true; } } if (!search) { remVars.add(node1); } } this.variables.removeAll(remVars); }
//////////////////////////////////////////// // 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"); } } }
/** * 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()); }
private Void findSeeds() { Tetrad tetrad = null; List<Node> empty = new ArrayList(); if (variables.size() < 4) { Set<Set<Integer>> ESeeds = new HashSet<Set<Integer>>(); } Map<Node, Set<Node>> adjacencies; if (depth == -2) { adjacencies = new HashMap<Node, Set<Node>>(); for (Node node : variables) { HashSet<Node> _nodes = new HashSet<Node>(variables); _nodes.remove(node); adjacencies.put(node, _nodes); } } else { // System.out.println("Running PC adjacency search..."); Graph graph = new EdgeListGraph(variables); Fas fas = new Fas(graph, indTest); fas.setVerbose(false); fas.setDepth(depth); // 1? adjacencies = fas.searchMapOnly(); // System.out.println("...done."); } List<Integer> allVariables = new ArrayList<Integer>(); for (int i = 0; i < variables.size(); i++) allVariables.add(i); log("Finding seeds.", true); ChoiceGenerator gen = new ChoiceGenerator(allVariables.size(), 3); int[] choice; CHOICE: while ((choice = gen.next()) != null) { int n1 = allVariables.get(choice[0]); int n2 = allVariables.get(choice[1]); int n3 = allVariables.get(choice[2]); Node v1 = variables.get(choice[0]); Node v2 = variables.get(choice[1]); Node v3 = variables.get(choice[2]); Set<Integer> triple = triple(n1, n2, n3); if (!clique(triple, adjacencies)) { continue; } boolean EPure = true; boolean CPure1 = true; boolean CPure2 = true; boolean CPure3 = true; for (int o : allVariables) { if (triple.contains(o)) { continue; } Node v4 = variables.get(o); tetrad = new Tetrad(v1, v2, v3, v4); if (deltaTest.getPValue(tetrad) > alpha) { EPure = false; if (indTest.isDependent(v1, v4, empty)) { CPure1 = false; } if (indTest.isDependent(v2, v4, empty)) { CPure2 = false; } } tetrad = new Tetrad(v1, v3, v2, v4); if (deltaTest.getPValue(tetrad) > alpha) { EPure = false; if (indTest.isDependent(v3, v4, empty)) { CPure3 = false; } } if (!(EPure || CPure1 || CPure2 || CPure3)) { continue CHOICE; } } HashSet<Integer> _cluster = new HashSet<Integer>(triple); if (verbose) { log("++" + variablesForIndices(new ArrayList<Integer>(triple)), false); } if (EPure) { ESeeds.add(_cluster); } if (!EPure) { if (CPure1) { Set<Integer> _cluster1 = new HashSet<Integer>(n2, n3); _cluster1.addAll(CSeeds.get(n1)); CSeeds.set(n1, _cluster1); } if (CPure2) { Set<Integer> _cluster2 = new HashSet<Integer>(n1, n3); _cluster2.addAll(CSeeds.get(n2)); CSeeds.set(n2, _cluster2); } if (CPure3) { Set<Integer> _cluster3 = new HashSet<Integer>(n1, n2); _cluster3.addAll(CSeeds.get(n3)); CSeeds.set(n3, _cluster3); } } } return null; }