private void correlateExogenousVariables() { Graph graph = getWorkbench().getGraph(); if (graph instanceof Dag) { JOptionPane.showMessageDialog( JOptionUtils.centeringComp(), "Cannot add bidirected edges to DAG's."); return; } List<Node> nodes = graph.getNodes(); List<Node> exoNodes = new LinkedList<Node>(); for (int i = 0; i < nodes.size(); i++) { Node node = nodes.get(i); if (graph.isExogenous(node)) { exoNodes.add(node); } } for (int i = 0; i < exoNodes.size(); i++) { loop: for (int j = i + 1; j < exoNodes.size(); j++) { Node node1 = exoNodes.get(i); Node node2 = exoNodes.get(j); List<Edge> edges = graph.getEdges(node1, node2); for (int k = 0; k < edges.size(); k++) { Edge edge = edges.get(k); if (Edges.isBidirectedEdge(edge)) { continue loop; } } graph.addBidirectedEdge(node1, node2); } } }
/** * Transforms a DAG represented in graph <code>graph</code> into a maximally directed pattern * (PDAG) by modifying <code>g</code> itself. Based on the algorithm described in Chickering * (2002) "Optimal structure identification with greedy search" Journal of Machine Learning * Research. It works for both BayesNets and SEMs. R. Silva, June 2004 */ public static void dagToPdag(Graph graph) { // do topological sort on the nodes Graph graphCopy = new EdgeListGraph(graph); Node orderedNodes[] = new Node[graphCopy.getNodes().size()]; int count = 0; while (graphCopy.getNodes().size() > 0) { Set<Node> exogenousNodes = new HashSet<Node>(); for (Node next : graphCopy.getNodes()) { if (graphCopy.isExogenous(next)) { exogenousNodes.add(next); orderedNodes[count++] = graph.getNode(next.getName()); } } graphCopy.removeNodes(new ArrayList<Node>(exogenousNodes)); } // ordered edges - improvised, inefficient implementation count = 0; Edge edges[] = new Edge[graph.getNumEdges()]; boolean edgeOrdered[] = new boolean[graph.getNumEdges()]; Edge orderedEdges[] = new Edge[graph.getNumEdges()]; for (Edge edge : graph.getEdges()) { edges[count++] = edge; } for (int i = 0; i < edges.length; i++) { edgeOrdered[i] = false; } while (count > 0) { for (Node orderedNode : orderedNodes) { for (int k = orderedNodes.length - 1; k >= 0; k--) { for (int q = 0; q < edges.length; q++) { if (!edgeOrdered[q] && edges[q].getNode1() == orderedNodes[k] && edges[q].getNode2() == orderedNode) { edgeOrdered[q] = true; orderedEdges[orderedEdges.length - count] = edges[q]; count--; } } } } } // label edges boolean compelledEdges[] = new boolean[graph.getNumEdges()]; boolean reversibleEdges[] = new boolean[graph.getNumEdges()]; for (int i = 0; i < graph.getNumEdges(); i++) { compelledEdges[i] = false; reversibleEdges[i] = false; } for (int i = 0; i < graph.getNumEdges(); i++) { if (compelledEdges[i] || reversibleEdges[i]) { continue; } Node x = orderedEdges[i].getNode1(); Node y = orderedEdges[i].getNode2(); for (int j = 0; j < orderedEdges.length; j++) { if (orderedEdges[j].getNode2() == x && compelledEdges[j]) { Node w = orderedEdges[j].getNode1(); if (!graph.isParentOf(w, y)) { for (int k = 0; k < orderedEdges.length; k++) { if (orderedEdges[k].getNode2() == y) { compelledEdges[k] = true; break; } } } else { for (int k = 0; k < orderedEdges.length; k++) { if (orderedEdges[k].getNode1() == w && orderedEdges[k].getNode2() == y) { compelledEdges[k] = true; break; } } } } if (compelledEdges[i]) { break; } } if (compelledEdges[i]) { continue; } boolean foundZ = false; for (Edge orderedEdge : orderedEdges) { Node z = orderedEdge.getNode1(); if (z != x && orderedEdge.getNode2() == y && !graph.isParentOf(z, x)) { compelledEdges[i] = true; for (int k = i + 1; k < graph.getNumEdges(); k++) { if (orderedEdges[k].getNode2() == y && !reversibleEdges[k]) { compelledEdges[k] = true; } } foundZ = true; break; } } if (!foundZ) { reversibleEdges[i] = true; for (int j = i + 1; j < orderedEdges.length; j++) { if (!compelledEdges[j] && orderedEdges[j].getNode2() == y) { reversibleEdges[j] = true; } } } } // undirect edges that are reversible for (int i = 0; i < reversibleEdges.length; i++) { if (reversibleEdges[i]) { graph.setEndpoint(orderedEdges[i].getNode1(), orderedEdges[i].getNode2(), Endpoint.TAIL); graph.setEndpoint(orderedEdges[i].getNode2(), orderedEdges[i].getNode1(), Endpoint.TAIL); } } }