Example #1
0
 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);
 }
Example #2
0
  private boolean existsUnblockedSemiDirectedPath(Node from, Node to, List<Node> cond, Graph G) {
    Queue<Node> Q = new LinkedList<Node>();
    Set<Node> V = new HashSet<Node>();
    Q.offer(from);
    V.add(from);

    while (!Q.isEmpty()) {
      Node t = Q.remove();
      if (t == to) return true;

      for (Node u : G.getAdjacentNodes(t)) {
        Edge edge = G.getEdge(t, u);
        Node c = Edges.traverseSemiDirected(t, edge);
        if (c == null) continue;
        if (cond.contains(c)) continue;
        if (c == to) return true;

        if (!V.contains(c)) {
          V.add(c);
          Q.offer(c);
        }
      }
    }

    return false;
  }
  /**
   * Transforms a maximally directed pattern (PDAG) represented in graph <code>g</code> into an
   * arbitrary DAG 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. R. Silva, June 2004
   */
  public static void pdagToDag(Graph g) {
    Graph p = new EdgeListGraph(g);
    List<Edge> undirectedEdges = new ArrayList<Edge>();

    for (Edge edge : g.getEdges()) {
      if (edge.getEndpoint1() == Endpoint.TAIL
          && edge.getEndpoint2() == Endpoint.TAIL
          && !undirectedEdges.contains(edge)) {
        undirectedEdges.add(edge);
      }
    }
    g.removeEdges(undirectedEdges);
    List<Node> pNodes = p.getNodes();

    do {
      Node x = null;

      for (Node pNode : pNodes) {
        x = pNode;

        if (p.getChildren(x).size() > 0) {
          continue;
        }

        Set<Node> neighbors = new HashSet<Node>();

        for (Edge edge : p.getEdges()) {
          if (edge.getNode1() == x || edge.getNode2() == x) {
            if (edge.getEndpoint1() == Endpoint.TAIL && edge.getEndpoint2() == Endpoint.TAIL) {
              if (edge.getNode1() == x) {
                neighbors.add(edge.getNode2());
              } else {
                neighbors.add(edge.getNode1());
              }
            }
          }
        }
        if (neighbors.size() > 0) {
          Collection<Node> parents = p.getParents(x);
          Set<Node> all = new HashSet<Node>(neighbors);
          all.addAll(parents);
          if (!GraphUtils.isClique(all, p)) {
            continue;
          }
        }

        for (Node neighbor : neighbors) {
          Node node1 = g.getNode(neighbor.getName());
          Node node2 = g.getNode(x.getName());

          g.addDirectedEdge(node1, node2);
        }
        p.removeNode(x);
        break;
      }
      pNodes.remove(x);
    } while (pNodes.size() > 0);
  }
Example #4
0
  /**
   * Step C of PC; orients colliders using specified sepset. That is, orients x *-* y *-* z as x *->
   * y <-* z just in case y is in Sepset({x, z}).
   */
  public Map<Triple, Double> findCollidersUsingSepsets(
      SepsetProducer sepsetProducer, Graph graph, boolean verbose, IKnowledge knowledge) {
    TetradLogger.getInstance().log("details", "Starting Collider Orientation:");
    Map<Triple, Double> colliders = new HashMap<>();

    System.out.println("Looking for colliders");

    List<Node> nodes = graph.getNodes();

    for (Node b : nodes) {
      List<Node> adjacentNodes = graph.getAdjacentNodes(b);

      if (adjacentNodes.size() < 2) {
        continue;
      }

      ChoiceGenerator cg = new ChoiceGenerator(adjacentNodes.size(), 2);
      int[] combination;

      while ((combination = cg.next()) != null) {
        Node a = adjacentNodes.get(combination[0]);
        Node c = adjacentNodes.get(combination[1]);

        // Skip triples that are shielded.
        if (graph.isAdjacentTo(a, c)) {
          continue;
        }

        List<Node> sepset = sepsetProducer.getSepset(a, c);

        if (sepset == null) continue;

        //                if (sepsetProducer.getPValue() < 0.5) continue;

        if (!sepset.contains(b)) {
          if (verbose) {
            //                        boolean dsep = this.dsep.isIndependent(a, c);
            //                        System.out.println("QQQ p = " + independenceTest.getPValue() +
            // " " + dsep);

            System.out.println(
                "\nCollider orientation <" + a + ", " + b + ", " + c + "> sepset = " + sepset);
          }

          colliders.put(new Triple(a, b, c), sepsetProducer.getPValue());

          TetradLogger.getInstance()
              .log("colliderOrientations", SearchLogUtils.colliderOrientedMsg(a, b, c, sepset));
        }
      }
    }

    TetradLogger.getInstance().log("details", "Finishing Collider Orientation.");

    System.out.println("Done finding colliders");

    return colliders;
  }
Example #5
0
  private void addColliders(
      Graph graph, final SepsetProducer sepsetProducer, IKnowledge knowledge) {
    final Map<Triple, Double> collidersPs =
        findCollidersUsingSepsets(sepsetProducer, graph, verbose, knowledge);

    List<Triple> colliders = new ArrayList<>(collidersPs.keySet());

    Collections.shuffle(colliders);

    Collections.sort(
        colliders,
        new Comparator<Triple>() {
          public int compare(Triple o1, Triple o2) {
            return -Double.compare(collidersPs.get(o1), collidersPs.get(o2));
          }
        });

    if (trueDag != null) {
      for (Triple collider : colliders) {
        Node a = collider.getX();
        Node b = collider.getY();
        Node c = collider.getZ();

        List<Node> sep = trueDag.getSepset(a, c);

        System.out.println(
            "JJJ "
                + collider
                + " collider = "
                + (sep != null && !sep.contains(b))
                + " p = "
                + collidersPs.get(collider));
      }
    }

    for (Triple collider : colliders) {
      Node a = collider.getX();
      Node b = collider.getY();
      Node c = collider.getZ();

      if (!(isArrowpointAllowed(a, b, knowledge) && isArrowpointAllowed(c, b, knowledge))) {
        continue;
      }

      if (!graph.getEdge(a, b).pointsTowards(a) && !graph.getEdge(b, c).pointsTowards(c)) {
        graph.setEndpoint(a, b, Endpoint.ARROW);
        graph.setEndpoint(c, b, Endpoint.ARROW);
      }
    }
  }
Example #6
0
  private void ruleR1(Graph skeleton, Graph graph, List<Node> nodes) {
    for (Node node : nodes) {
      SortedMap<Double, String> scoreReports = new TreeMap<Double, String>();

      List<Node> adj = skeleton.getAdjacentNodes(node);

      DepthChoiceGenerator gen = new DepthChoiceGenerator(adj.size(), adj.size());
      int[] choice;
      double maxScore = Double.NEGATIVE_INFINITY;
      List<Node> parents = null;

      while ((choice = gen.next()) != null) {
        List<Node> _parents = GraphUtils.asList(choice, adj);

        double score = score(node, _parents);
        scoreReports.put(-score, _parents.toString());

        if (score > maxScore) {
          maxScore = score;
          parents = _parents;
        }
      }

      for (double score : scoreReports.keySet()) {
        TetradLogger.getInstance()
            .log(
                "score",
                "For " + node + " parents = " + scoreReports.get(score) + " score = " + -score);
      }

      TetradLogger.getInstance().log("score", "");

      if (parents == null) {
        continue;
      }

      if (normal(node, parents)) continue;

      for (Node _node : adj) {
        if (parents.contains(_node)) {
          Edge parentEdge = Edges.directedEdge(_node, node);

          if (!graph.containsEdge(parentEdge)) {
            graph.addEdge(parentEdge);
          }
        }
      }
    }
  }
Example #7
0
  /**
   * @param node The variable node in question.
   * @return the error node for the given node.
   */
  public Node getErrorNode(Node node) {
    if (errorNodes.contains(node)) {
      return node;
    }

    int index = variableNodes.indexOf(node);

    if (index == -1) {
      throw new NullPointerException(
          node
              + " is not a node in this model. Perhaps "
              + "it's another node with the same name.");
    }

    return errorNodes.get(index);
  }
  public static boolean existsLocalSepsetWithoutDet(
      Node x, Node y, Node z, IndependenceTest test, Graph graph, int depth) {
    Set<Node> __nodes = new HashSet<Node>(graph.getAdjacentNodes(x));
    __nodes.addAll(graph.getAdjacentNodes(z));
    __nodes.remove(x);
    __nodes.remove(z);
    List<Node> _nodes = new LinkedList<Node>(__nodes);
    TetradLogger.getInstance()
        .log("adjacencies", "Adjacents for " + x + "--" + y + "--" + z + " = " + _nodes);

    int _depth = depth;
    if (_depth == -1) {
      _depth = 1000;
    }
    _depth = Math.min(_depth, _nodes.size());

    for (int d = 0; d <= _depth; d++) {
      if (_nodes.size() >= d) {
        ChoiceGenerator cg2 = new ChoiceGenerator(_nodes.size(), d);
        int[] choice;

        while ((choice = cg2.next()) != null) {
          List<Node> condSet = asList(choice, _nodes);

          if (condSet.contains(y)) {
            continue;
          }

          if (test.determines(condSet, y)) {
            continue;
          }

          //        LogUtils.getInstance().finest("Trying " + condSet);

          if (test.isIndependent(x, z, condSet)) {
            return true;
          }
        }
      }
    }

    return false;
  }
  /**
   * Step C of PC; orients colliders using specified sepset. That is, orients x *-* y *-* z as x *->
   * y <-* z just in case y is in Sepset({x, z}).
   */
  public static void orientCollidersUsingSepsets(SepsetMap set, Knowledge knowledge, Graph graph) {
    TetradLogger.getInstance().log("info", "Starting Collider Orientation:");

    //        verifySepsetIntegrity(set, graph);

    List<Node> nodes = graph.getNodes();

    for (Node a : nodes) {
      List<Node> adjacentNodes = graph.getAdjacentNodes(a);

      if (adjacentNodes.size() < 2) {
        continue;
      }

      ChoiceGenerator cg = new ChoiceGenerator(adjacentNodes.size(), 2);
      int[] combination;

      while ((combination = cg.next()) != null) {
        Node b = adjacentNodes.get(combination[0]);
        Node c = adjacentNodes.get(combination[1]);

        // Skip triples that are shielded.
        if (graph.isAdjacentTo(b, c)) {
          continue;
        }

        List<Node> sepset = set.get(b, c);
        if (sepset != null
            && !sepset.contains(a)
            && isArrowpointAllowed(b, a, knowledge)
            && isArrowpointAllowed(c, a, knowledge)) {
          graph.setEndpoint(b, a, Endpoint.ARROW);
          graph.setEndpoint(c, a, Endpoint.ARROW);
          TetradLogger.getInstance()
              .log("colliderOriented", SearchLogUtils.colliderOrientedMsg(b, a, c, sepset));
        }
      }
    }

    TetradLogger.getInstance().log("info", "Finishing Collider Orientation.");
  }
  public static CpcTripleType getCpcTripleType(
      Node x, Node y, Node z, IndependenceTest test, int depth, Graph graph) {
    //    	System.out.println("getCpcTripleType 1");

    boolean existsSepsetContainingY = false;
    boolean existsSepsetNotContainingY = false;

    Set<Node> __nodes = new HashSet<Node>(graph.getAdjacentNodes(x));
    __nodes.remove(z);

    //    	System.out.println("getCpcTripleType 2");

    List<Node> _nodes = new LinkedList<Node>(__nodes);
    TetradLogger.getInstance()
        .log("adjacencies", "Adjacents for " + x + "--" + y + "--" + z + " = " + _nodes);

    //        System.out.println("getCpcTripleType 3");

    int _depth = depth;
    if (_depth == -1) {
      _depth = 1000;
    }
    _depth = Math.min(_depth, _nodes.size());

    //    	System.out.println("getCpcTripleType 4");

    for (int d = 0; d <= _depth; d++) {
      //        	System.out.println("getCpcTripleType 5");

      ChoiceGenerator cg = new ChoiceGenerator(_nodes.size(), d);
      int[] choice;

      while ((choice = cg.next()) != null) {
        //            	System.out.println("getCpcTripleType 6");

        List<Node> condSet = GraphUtils.asList(choice, _nodes);

        //            	System.out.println("getCpcTripleType 7");

        if (test.isIndependent(x, z, condSet)) {
          if (condSet.contains(y)) {
            existsSepsetContainingY = true;
          } else {
            existsSepsetNotContainingY = true;
          }
        }
      }
    }

    //    	System.out.println("getCpcTripleType 8");

    __nodes = new HashSet<Node>(graph.getAdjacentNodes(z));
    __nodes.remove(x);

    _nodes = new LinkedList<Node>(__nodes);
    TetradLogger.getInstance()
        .log("adjacencies", "Adjacents for " + x + "--" + y + "--" + z + " = " + _nodes);

    //    	System.out.println("getCpcTripleType 9");

    _depth = depth;
    if (_depth == -1) {
      _depth = 1000;
    }
    _depth = Math.min(_depth, _nodes.size());

    //    	System.out.println("getCpcTripleType 10");

    for (int d = 0; d <= _depth; d++) {
      //        	System.out.println("getCpcTripleType 11");

      ChoiceGenerator cg = new ChoiceGenerator(_nodes.size(), d);
      int[] choice;

      while ((choice = cg.next()) != null) {
        List<Node> condSet = GraphUtils.asList(choice, _nodes);

        if (test.isIndependent(x, z, condSet)) {
          if (condSet.contains(y)) {
            existsSepsetContainingY = true;
          } else {
            existsSepsetNotContainingY = true;
          }
        }
      }
    }

    //    	System.out.println("getCpcTripleType 12");

    if (existsSepsetContainingY == existsSepsetNotContainingY) {
      return CpcTripleType.AMBIGUOUS;
    } else if (!existsSepsetNotContainingY) {
      return CpcTripleType.NONCOLLIDER;
    } else {
      return CpcTripleType.COLLIDER;
    }
  }
Example #11
0
  ////////////////////////////////////////////
  // 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");
      }
    }
  }
Example #12
0
  public void setNodeExpression(Node node, String expressionString) throws ParseException {
    if (node == null) {
      throw new NullPointerException("Node was null.");
    }

    if (expressionString == null) {
      //            return;
      throw new NullPointerException("Expression string was null.");
    }

    // Parse the expression. This could throw an ParseException, but that exception needs to handed
    // up the
    // chain, because the interface will need it.
    ExpressionParser parser = new ExpressionParser();
    Expression expression = parser.parseExpression(expressionString);
    List<String> parameterNames = parser.getParameters();

    // Make a list of parent names.
    List<Node> parents = this.graph.getParents(node);
    List<String> parentNames = new LinkedList<>();

    for (Node parent : parents) {
      parentNames.add(parent.getName());
    }

    //        List<String> _params = new ArrayList<String>(parameterNames);
    //        _params.retainAll(variableNames);
    //        _params.removeAll(parentNames);
    //
    //        if (!_params.isEmpty()) {
    //            throw new IllegalArgumentException("Conditioning on a variable other than the
    // parents: " + node);
    //        }

    // Make a list of parameter names, by removing from the parser's list of freeParameters any that
    // correspond
    // to parent variables. If there are any variable names (including error terms) that are not
    // among the list of
    // parents, that's a time to throw an exception. We must respect the graph! (We will not
    // complain if any parents
    // are missing.)
    parameterNames.removeAll(variableNames);

    for (Node variable : nodes) {
      if (parameterNames.contains(variable.getName())) {
        parameterNames.remove(variable.getName());
        //                throw new IllegalArgumentException("The list of parameter names may not
        // include variables: " + variable.getName());
      }
    }

    // Remove old parameter references.
    List<String> parametersToRemove = new LinkedList<>();

    for (String parameter : this.referencedParameters.keySet()) {
      Set<Node> nodes = this.referencedParameters.get(parameter);

      if (nodes.contains(node)) {
        nodes.remove(node);
      }

      if (nodes.isEmpty()) {
        parametersToRemove.add(parameter);
      }
    }

    for (String parameter : parametersToRemove) {
      this.referencedParameters.remove(parameter);
      this.parameterExpressions.remove(parameter);
      this.parameterExpressionStrings.remove(parameter);
      this.parameterEstimationInitializationExpressions.remove(parameter);
      this.parameterEstimationInitializationExpressionStrings.remove(parameter);
    }

    // Add new parameter references.
    for (String parameter : parameterNames) {
      if (this.referencedParameters.get(parameter) == null) {
        this.referencedParameters.put(parameter, new HashSet<Node>());
      }

      Set<Node> nodes = this.referencedParameters.get(parameter);
      nodes.add(node);

      setSuitableParameterDistribution(parameter);
    }

    // Remove old node references.
    List<Node> nodesToRemove = new LinkedList<>();

    for (Node _node : this.referencedNodes.keySet()) {
      Set<Node> nodes = this.referencedNodes.get(_node);

      if (nodes.contains(node)) {
        nodes.remove(node);
      }

      if (nodes.isEmpty()) {
        nodesToRemove.add(_node);
      }
    }

    for (Node _node : nodesToRemove) {
      this.referencedNodes.remove(_node);
    }

    // Add new freeParameters.
    for (String variableString : variableNames) {
      Node _node = getNode(variableString);

      if (this.referencedNodes.get(_node) == null) {
        this.referencedNodes.put(_node, new HashSet<Node>());
      }

      for (String s : parentNames) {
        if (s.equals(variableString)) {
          Set<Node> nodes = this.referencedNodes.get(_node);
          nodes.add(node);
        }
      }
    }

    // Finally, save the parsed expression and the original string that the user entered. No need to
    // annoy
    // the user by changing spacing.
    nodeExpressions.put(node, expression);
    nodeExpressionStrings.put(node, expressionString);
  }
Example #13
0
  public GeneralizedSemPm(SemPm semPm) {
    this(semPm.getGraph());

    // Write down equations.
    try {
      List<Node> variableNodes = getVariableNodes();

      for (int i = 0; i < variableNodes.size(); i++) {
        Node node = variableNodes.get(i);
        List<Node> parents = getVariableParents(node);

        StringBuilder buf = new StringBuilder();

        for (int j = 0; j < parents.size(); j++) {
          if (!(variableNodes.contains(parents.get(j)))) {
            continue;
          }

          Node parent = parents.get(j);

          Parameter _parameter = semPm.getParameter(parent, node);
          String parameter = _parameter.getName();
          Set<Node> nodes = new HashSet<>();
          nodes.add(node);

          referencedParameters.put(parameter, nodes);

          buf.append(parameter);
          buf.append("*");
          buf.append(parents.get(j).getName());

          setParameterExpression(parameter, "Split(-1.5, -.5, .5, 1.5)");
          setStartsWithParametersTemplate(parameter.substring(0, 1), "Split(-1.5, -.5, .5, 1.5)");
          setStartsWithParametersEstimationInitializaationTemplate(
              parameter.substring(0, 1), "Split(-1.5, -.5, .5, 1.5)");

          if (j < parents.size() - 1) {
            buf.append(" + ");
          }
        }

        if (buf.toString().trim().length() != 0) {
          buf.append(" + ");
        }

        buf.append(errorNodes.get(i));
        setNodeExpression(node, buf.toString());
      }

      for (Node node : variableNodes) {
        Parameter _parameter = semPm.getParameter(node, node);
        String parameter = _parameter.getName();

        String distributionFormula = "N(0," + parameter + ")";
        setNodeExpression(getErrorNode(node), distributionFormula);
        setParameterExpression(parameter, "U(0, 1)");
        setStartsWithParametersTemplate(parameter.substring(0, 1), "U(0, 1)");
        setStartsWithParametersEstimationInitializaationTemplate(
            parameter.substring(0, 1), "U(0, 1)");
      }

      variableNames = new ArrayList<>();
      for (Node _node : variableNodes) variableNames.add(_node.getName());
      for (Node _node : errorNodes) variableNames.add(_node.getName());

    } catch (ParseException e) {
      throw new IllegalStateException("Parse error in constructing initial model.", e);
    }
  }