/** Constructs a new SemPm from the given SemGraph. */ public GeneralizedSemPm(SemGraph graph) { if (graph == null) { throw new NullPointerException("Graph must not be null."); } // if (graph.existsDirectedCycle()) { // throw new IllegalArgumentExcneption("Cycles are not supported."); // } // Cannot afford to allow error terms on this graph to be shown or hidden from the outside; must // make a // hidden copy of it and make sure error terms are shown. this.graph = new SemGraph(graph); this.graph.setShowErrorTerms(true); for (Edge edge : this.graph.getEdges()) { if (Edges.isBidirectedEdge(edge)) { throw new IllegalArgumentException( "The generalized SEM PM cannot currently deal with bidirected " + "edges. Sorry."); } } this.nodes = Collections.unmodifiableList(this.graph.getNodes()); for (Node node : nodes) { namesToNodes.put(node.getName(), node); } this.variableNodes = new ArrayList<>(); this.measuredNodes = new ArrayList<>(); for (Node variable : this.nodes) { if (variable.getNodeType() == NodeType.MEASURED || variable.getNodeType() == NodeType.LATENT) { variableNodes.add(variable); } if (variable.getNodeType() == NodeType.MEASURED) { measuredNodes.add(variable); } } this.errorNodes = new ArrayList<>(); for (Node variable : this.variableNodes) { List<Node> parents = this.graph.getParents(variable); boolean added = false; for (Node _node : parents) { if (_node.getNodeType() == NodeType.ERROR) { errorNodes.add(_node); added = true; break; } } if (!added) { errorNodes.add(null); } } this.referencedParameters = new HashMap<>(); this.referencedNodes = new HashMap<>(); this.nodeExpressions = new HashMap<>(); this.nodeExpressionStrings = new HashMap<>(); this.parameterExpressions = new HashMap<>(); this.parameterExpressionStrings = new HashMap<>(); this.parameterEstimationInitializationExpressions = new HashMap<>(); this.parameterEstimationInitializationExpressionStrings = new HashMap<>(); this.startsWithParametersTemplates = new HashMap<>(); this.startsWithParametersEstimationInitializationTemplates = new HashMap<>(); this.variableNames = new ArrayList<>(); for (Node _node : variableNodes) variableNames.add(_node.getName()); for (Node _node : errorNodes) variableNames.add(_node.getName()); try { List<Node> variableNodes = getVariableNodes(); for (Node node : variableNodes) { if (!this.graph.isParameterizable(node)) continue; if (nodeExpressions.get(node) != null) { continue; } String variablestemplate = getVariablesTemplate(); String formula = TemplateExpander.getInstance().expandTemplate(variablestemplate, this, node); setNodeExpression(node, formula); Set<String> parameters = getReferencedParameters(node); String parametersTemplate = getParametersTemplate(); for (String parameter : parameters) { if (parameterExpressions.get(parameter) == null) { if (parametersTemplate != null) { setParameterExpression(parameter, parametersTemplate); } else if (this.graph.isTimeLagModel()) { String expressionString = "Split(-0.9, -.1, .1, 0.9)"; setParameterExpression(parameter, expressionString); setParametersTemplate(expressionString); } else { String expressionString = "Split(-1.5, -.5, .5, 1.5)"; setParameterExpression(parameter, expressionString); setParametersTemplate(expressionString); } } } for (String parameter : parameters) { if (parameterEstimationInitializationExpressions.get(parameter) == null) { if (parametersTemplate != null) { setParameterEstimationInitializationExpression(parameter, parametersTemplate); } else if (this.graph.isTimeLagModel()) { String expressionString = "Split(-0.9, -.1, .1, 0.9)"; setParameterEstimationInitializationExpression(parameter, expressionString); } else { String expressionString = "Split(-1.5, -.5, .5, 1.5)"; setParameterEstimationInitializationExpression(parameter, expressionString); } } setStartsWithParametersTemplate("s", "Split(-1.5, -.5, .5, 1.5)"); setStartsWithParametersEstimationInitializaationTemplate( "s", "Split(-1.5, -.5, .5, 1.5)"); } } for (Node node : errorNodes) { if (node == null) continue; String template = getErrorsTemplate(); String formula = TemplateExpander.getInstance().expandTemplate(template, this, node); setNodeExpression(node, formula); Set<String> parameters = getReferencedParameters(node); setStartsWithParametersTemplate("s", "U(1, 3)"); setStartsWithParametersEstimationInitializaationTemplate("s", "U(1, 3)"); for (String parameter : parameters) { setParameterExpression(parameter, "U(1, 3)"); } } } catch (ParseException e) { throw new IllegalStateException("Parse error in constructing initial model.", e); } }
@Test public void test4() { // For X3 Map<String, String[]> templates = new HashMap<>(); templates.put( "NEW(b) + NEW(b) + NEW(c) + NEW(c) + NEW(c)", new String[] {"X1", "X2", "X3", "X4", "X5"}); templates.put("NEW(X1) + NEW(b) + NEW(c) + NEW(c) + NEW(c)", new String[] {}); templates.put("$", new String[] {}); templates.put("TSUM($)", new String[] {"X1", "X2", "X3", "X4", "X5"}); templates.put("TPROD($)", new String[] {"X1", "X2", "X3", "X4", "X5"}); templates.put("TPROD($) + X2", new String[] {"X1", "X2", "X3", "X4", "X5"}); templates.put("TPROD($) + TSUM($)", new String[] {"X1", "X2", "X3", "X4", "X5"}); templates.put("tan(TSUM(NEW(a)*$))", new String[] {"X1", "X2", "X3", "X4", "X5"}); templates.put("Normal(0, 1)", new String[] {"X1", "X2", "X3", "X4", "X5"}); templates.put("Normal(m, s)", new String[] {"X1", "X2", "X3", "X4", "X5"}); templates.put("Normal(NEW(m), s)", new String[] {"X1", "X2", "X3", "X4", "X5"}); templates.put("Normal(NEW(m), NEW(s)) + m1 + s6", new String[] {"X1", "X2", "X3", "X4", "X5"}); templates.put("TSUM($) + a", new String[] {"X1", "X2", "X3", "X4", "X5"}); templates.put("TSUM($) + TSUM($) + TSUM($) + 1", new String[] {"X1", "X2", "X3", "X4", "X5"}); for (String template : templates.keySet()) { GeneralizedSemPm semPm = makeTypicalPm(); print(semPm.getGraph().toString()); Set<Node> shouldWork = new HashSet<>(); for (String name : templates.get(template)) { shouldWork.add(semPm.getNode(name)); } Set<Node> works = new HashSet<>(); for (int i = 0; i < semPm.getNodes().size(); i++) { print("-----------"); print(semPm.getNodes().get(i).toString()); print("Trying template: " + template); String _template = template; Node node = semPm.getNodes().get(i); try { _template = TemplateExpander.getInstance().expandTemplate(_template, semPm, node); } catch (Exception e) { print("Couldn't expand template: " + template); continue; } try { semPm.setNodeExpression(node, _template); print("Set formula " + _template + " for " + node); if (semPm.getVariableNodes().contains(node)) { works.add(node); } } catch (Exception e) { print("Couldn't set formula " + _template + " for " + node); } } for (String parameter : semPm.getParameters()) { print("-----------"); print(parameter); print("Trying template: " + template); String _template = template; try { _template = TemplateExpander.getInstance().expandTemplate(_template, semPm, null); } catch (Exception e) { print("Couldn't expand template: " + template); continue; } try { semPm.setParameterExpression(parameter, _template); print("Set formula " + _template + " for " + parameter); } catch (Exception e) { print("Couldn't set formula " + _template + " for " + parameter); } } assertEquals(shouldWork, works); } }