/** * Collect all CalculationNodes on a path from any StateNode that is changed (as indicated by * m_changedStateNodeCode) to the posterior. Return the list in partial order as determined by the * BEASTObjects input relations. */ private List<CalculationNode> calculateCalcNodePath() throws Exception { final List<CalculationNode> calcNodes = new ArrayList<>(); // for (int i = 0; i < stateNode.length; i++) { // if (m_changedStateNodeCode.get(i)) { for (int k = 0; k < nrOfChangedStateNodes; k++) { int i = changeStateNodes[k]; // go grab the path to the Runnable // first the outputs of the StateNodes that is changed boolean progress = false; for (CalculationNode node : stateNodeOutputs[i]) { if (!calcNodes.contains(node)) { calcNodes.add(node); progress = true; } } // next the path following the outputs while (progress) { progress = false; // loop over beastObjects till no more beastObjects can be added // efficiency is no issue here, assuming the graph remains // constant for (int calcNodeIndex = 0; calcNodeIndex < calcNodes.size(); calcNodeIndex++) { CalculationNode node = calcNodes.get(calcNodeIndex); for (BEASTInterface output : outputMap.get(node)) { if (output instanceof CalculationNode) { final CalculationNode calcNode = (CalculationNode) output; if (!calcNodes.contains(calcNode)) { calcNodes.add(calcNode); progress = true; } } else { throw new RuntimeException( "DEVELOPER ERROR: found a" + " non-CalculatioNode (" + output.getClass().getName() + ") on path between StateNode and Runnable"); } } } } // } } // put calc nodes in partial order for (int i = 0; i < calcNodes.size(); i++) { CalculationNode node = calcNodes.get(i); List<BEASTInterface> inputList = node.listActiveBEASTObjects(); for (int j = calcNodes.size() - 1; j > i; j--) { if (inputList.contains(calcNodes.get(j))) { // swap final CalculationNode node2 = calcNodes.get(j); calcNodes.set(j, node); calcNodes.set(i, node2); j = 0; i--; } } } return calcNodes; } // calculateCalcNodePath
/** * Sets the posterior, needed to calculate paths of CalculationNode that need * store/restore/requireCalculation checks. As a side effect, outputs for every beastObject in the * model are calculated. NB the output map only contains outputs on a path to the posterior * BEASTObject! */ @SuppressWarnings("unchecked") public void setPosterior(BEASTObject posterior) throws Exception { // first, calculate output map that maps BEASTObjects on a path // to the posterior to the list of output BEASTObjects. Strictly // speaking, this is a bit of overkill, since only // CalculationNodes need to be taken in account, but for // debugging purposes (developer forgot to derive from CalculationNode) // we keep track of the lot. outputMap = new HashMap<>(); outputMap.put(posterior, new ArrayList<>()); boolean progress = true; List<BEASTInterface> beastObjects = new ArrayList<>(); beastObjects.add(posterior); while (progress) { progress = false; // loop over plug-ins, till no more plug-ins can be added // efficiency is no issue here for (int i = 0; i < beastObjects.size(); i++) { BEASTInterface beastObject = beastObjects.get(i); try { for (BEASTInterface inputBEASTObject : beastObject.listActiveBEASTObjects()) { if (!outputMap.containsKey(inputBEASTObject)) { outputMap.put(inputBEASTObject, new ArrayList<>()); beastObjects.add(inputBEASTObject); progress = true; } if (!outputMap.get(inputBEASTObject).contains(beastObject)) { outputMap.get(inputBEASTObject).add(beastObject); progress = true; } } } catch (Exception e) { e.printStackTrace(); } } } // Set of array of StateNode outputs. Since the StateNodes have a potential // to be changing objects (when store/restore is applied) it is necessary // to use another method to find the outputs, an array in this case. stateNodeOutputs = new List[stateNode.length]; for (int i = 0; i < stateNode.length; i++) { stateNodeOutputs[i] = new ArrayList<>(); if (outputMap.containsKey(stateNode[i])) { for (BEASTInterface beastObject : outputMap.get(stateNode[i])) { if (beastObject instanceof CalculationNode) { stateNodeOutputs[i].add((CalculationNode) beastObject); } else { throw new RuntimeException( "DEVELOPER ERROR: output of StateNode (" + stateNode[i].getID() + ") should be a CalculationNode, but " + beastObject.getClass().getName() + " is not."); } } } else { Log.warning.println( "\nWARNING: StateNode (" + stateNode[i].getID() + ") found that has no effect on posterior!\n"); } } } // setPosterior