protected void setLayersDFS(PNode<V, E> node, int layer) { if (layer > node.getLayer()) { node.setLayer(layer); for (PEdge<V, E> edge : node.getChildren()) { setLayersDFS(edge.to, layer + 1); } } }
public void addEdge(Edge<V, E> edge) { assert !locked; PNode<V, E> pnodeFrom = nodeMap.get(edge.getFrom()); PNode<V, E> pnodeTo = nodeMap.get(edge.getTo()); PEdge<V, E> pedge = new PEdge<V, E>(edge, pnodeFrom, pnodeTo); pnodeFrom.addChild(pedge); pnodeTo.addParent(pedge); edges.add(pedge); }
private void fillTmpLGraph() { tmpLGraph.reset(); resetLayers(); for (PEdge<V, E> edge : root.getChildren()) { setLayersDFS(edge.to, 0); } for (PEdge<V, E> edge : root.getChildren()) { tmpLGraph.addNode(edge.to.node, edge.to.getLayer()); populateLGraph(tmpLGraph, edge.to); } }
public void lock() { if (locked) return; locked = true; nodesWithSeveralChildren = new ArrayList<PNode<V, E>>(); nodesWithSeveralChildrenScaled = new ArrayList<PNode<V, E>>(); nodesWithSeveralParents = new ArrayList<PNode<V, E>>(); nodesWithoutChildren = new ArrayList<PNode<V, E>>(); sourceFakeEdges = new ArrayList<PEdge<V, E>>(); for (PNode<V, E> pnode : nodes) { if (pnode.isSource()) { PEdge<V, E> fakeEdge = new PEdge<V, E>(root, pnode); pnode.addParent(fakeEdge); root.addChild(fakeEdge); sourceFakeEdges.add(fakeEdge); } if (pnode.getChildren().size() >= 2) { nodesWithSeveralChildren.add(pnode); int i = pnode.getChildren().size(); while (--i > 0) { nodesWithSeveralChildrenScaled.add(pnode); } } if (pnode.getParents().size() >= 2) { nodesWithSeveralParents.add(pnode); } if (pnode.getChildren().size() == 0) { nodesWithoutChildren.add(pnode); } } }
/* The difference to generateLGraph is that it tries to be really efficient, not visually appealing, by pulling nodes down etc. It's just supposed to be used for assessments, e.g. for the simulated annealing. */ public LGraph<V, E> generateLGraphEfficiently(LGraphConfig lconfig) { if (!locked) lock(); LGraph<V, E> lgraph = new LGraph<V, E>(lconfig); resetLayers(); for (PEdge<V, E> edge : root.getChildren()) { setLayersDFS(edge.to, 0); } for (PEdge<V, E> edge : root.getChildren()) { lgraph.addNode(edge.to.node, edge.to.getLayer()); populateLGraph(lgraph, edge.to); } return lgraph; }
protected void populateLGraph(LGraph<V, E> lgraph, PNode<V, E> node) { for (PEdge<V, E> edge : node.getChildren()) { if (!lgraph.containsNode(edge.to.node)) { lgraph.addNode(edge.to.node, edge.to.getLayer()); populateLGraph(lgraph, edge.to); } if (!edge.isFake) { lgraph.addEdge(edge.edge); } } }
public double trySwapChildren(double temp, double currentEnergy) { if (nodesWithSeveralChildrenScaled.size() > 0) { PNode<V, E> parent = nodesWithSeveralChildrenScaled.get( quadraticRandint(nodesWithSeveralChildrenScaled.size())); nodesWithSeveralChildrenScaled.remove(parent); nodesWithSeveralChildrenScaled.add( parent); // move it to the end - less likely to be picked again in near future int numberOfChildren = parent.getChildren().size(); int i1 = random.nextInt(numberOfChildren); int i2 = random.nextInt(numberOfChildren - 1); i2 = i2 >= i1 ? i2 + 1 : i2; parent.swapChildren(i1, i2); double newEnergy = getEnergy(); if (acceptChange(currentEnergy, newEnergy, temp)) { return newEnergy; } else { parent.swapChildren(i1, i2); // swap back return currentEnergy; } } return currentEnergy; }
boolean cycleDetector(PNode<V, E> node, HashMap<PNode<V, E>, Boolean> map) { if (!map.containsKey(node)) { map.put(node, true); } else if (map.get(node)) { return true; } else { map.put(node, true); } for (PEdge<V, E> edge : node.getChildren()) { if (cycleDetector(edge.to, map)) { return true; } } map.put(node, false); return false; }
public double tryAddFakeEdge(double temp, double currentEnergy) { // it's sufficient to only add fake edges from leaves to nodes with multiple parents if (nodesWithoutChildren.size() > 0 && nodesWithSeveralParents.size() > 0) { PNode<V, E> from = nodesWithoutChildren.get(random.nextInt(nodesWithoutChildren.size())); PNode<V, E> to = nodesWithSeveralParents.get(random.nextInt(nodesWithSeveralParents.size())); PEdge<V, E> fakeEdge = new PEdge<V, E>(from, to); from.addChild(fakeEdge); to.addParent(fakeEdge); if (!graphHasCycle(to)) { double newEnergy = getEnergy(); if (acceptChange(currentEnergy, newEnergy, temp)) { fakeEdges.add(fakeEdge); return newEnergy; } } // otherwise undo changes from.removeChild(fakeEdge); to.removeParent(fakeEdge); return currentEnergy; } return currentEnergy; }
public double tryChangeSource(double temp, double currentEnergy) { PEdge<V, E> fakeEdge = sourceFakeEdges.get(random.nextInt(sourceFakeEdges.size())); PNode<V, E> child = fakeEdge.to; int oldIndex = fakeEdge.from.getChildren().indexOf(fakeEdge); child.removeParent(fakeEdge); fakeEdge.from.removeChild(fakeEdge); PEdge<V, E> fakeEdge2; int fakeEdge2Swap = -1; if (fakeEdge.from.isRoot || random.nextDouble() < 0.4) { // try attaching it somewhere else PNode<V, E> parent; if (Math.random() < 0.5 || nodesWithSeveralChildrenScaled.size() == 0) { // try some completely random node parent = nodes.get(random.nextInt(nodes.size())); } else { parent = nodesWithSeveralChildrenScaled.get( random.nextInt(nodesWithSeveralChildrenScaled.size())); } fakeEdge2 = new PEdge<V, E>(parent, child); parent.addChild(fakeEdge2); if (parent.getChildren().size() > 1) { fakeEdge2Swap = random.nextInt(parent.getChildren().size() - 1); parent.swapChildren(parent.getChildren().size() - 1, fakeEdge2Swap); } child.addParent(fakeEdge2); } else { // try attaching it back to root. fakeEdge2 = new PEdge<V, E>(root, child); root.addChild(fakeEdge2); if (root.getChildren().size() > 1) { fakeEdge2Swap = random.nextInt(root.getChildren().size() - 1); root.swapChildren(root.getChildren().size() - 1, fakeEdge2Swap); } child.addParent(fakeEdge2); } if (!graphHasCycle(fakeEdge2.to)) { double newEnergy = getEnergy(); if (acceptChange(currentEnergy, newEnergy, temp)) { sourceFakeEdges.remove(fakeEdge); sourceFakeEdges.add(fakeEdge2); return newEnergy; } } fakeEdge2.from.removeChild(fakeEdge2); child.removeParent(fakeEdge2); if (fakeEdge2Swap != -1) { PEdge<V, E> e = fakeEdge2.from.getChildren().get(fakeEdge2.from.getChildren().size() - 1); fakeEdge2.from.getChildren().remove(fakeEdge2.from.getChildren().size() - 1); fakeEdge2.from.getChildren().add(fakeEdge2Swap, e); } // fakeEdge.from.addChild(fakeEdge); fakeEdge.from.getChildren().add(oldIndex, fakeEdge); child.addParent(fakeEdge); return currentEnergy; }
protected void resetLayers() { for (PNode<V, E> pnode : nodes) { pnode.resetLayer(); } }
protected void setLayers() { for (PEdge<V, E> edge : root.getChildren()) { setLayersDFS(edge.to, 0); } }