private JunctionTree graphToJt(UndirectedGraph g) {
    JunctionTree jt = new JunctionTree(g.vertexSet().size());
    Object root = g.vertexSet().iterator().next();
    jt.add(root);

    for (Iterator it1 = new BreadthFirstIterator(g, root); it1.hasNext(); ) {
      Object v1 = it1.next();
      for (Iterator it2 = GraphHelper.neighborListOf(g, v1).iterator(); it2.hasNext(); ) {
        Object v2 = it2.next();
        if (jt.getParent(v1) != v2) {
          jt.addNode(v1, v2);
        }
      }
    }
    return jt;
  }
 public void dump() {
   if (jtCurrent != null) {
     System.out.println("Current junction tree");
     jtCurrent.dump();
   } else {
     System.out.println("NO current junction tree");
   }
 }
  private void initJtCpts(FactorGraph mdl, JunctionTree jt) {
    for (Iterator it = jt.getVerticesIterator(); it.hasNext(); ) {
      VarSet c = (VarSet) it.next();
      //      DiscreteFactor ptl = createBlankFactor (c);
      //      jt.setCPF(c, ptl);
      jt.setCPF(c, new ConstantFactor(1.0));
    }

    for (Iterator it = mdl.factors().iterator(); it.hasNext(); ) {
      Factor ptl = (Factor) it.next();
      VarSet parent = jt.findParentCluster(ptl.varSet());
      assert parent != null : "Unable to find parent cluster for ptl " + ptl + "in jt " + jt;

      Factor cpf = jt.getCPF(parent);
      Factor newCpf = cpf.multiply(ptl);
      jt.setCPF(parent, newCpf);

      /* debug
      if (jt.isNaN()) {
        throw new RuntimeException ("Got a NaN");
      }
      */
    }
  }
  /**
   * Constructs a junction tree from a given factor graph. Does not perform BP in the resulting
   * graph. So this gives you the structure of a jnuction tree, but the factors don't correspond to
   * the true marginals unless you call BP yourself.
   *
   * @param mdl Factor graph to compute JT for.
   */
  public JunctionTree buildJunctionTree(FactorGraph mdl) {
    jtCurrent = (JunctionTree) mdl.getInferenceCache(JunctionTreeInferencer.class);
    if (jtCurrent != null) {
      jtCurrent.clearCPFs();
    } else {
      /* The graph g is the topology of the MRF that corresponds to the factor graph mdl.
       * Essentially, this means that we triangulate factor graphs by converting to an MRF first.
       * I could have chosen to trianglualte the FactorGraph directly, but I didn't for historical reasons
       *  (I already had a version of triangulate() for MRFs, not bipartite factor graphs.)
       * Note that the call to mdlToGraph() is perfectly valid for FactorGraphs that are also DirectedModels,
       *  and has the effect of moralizing in that case.  */
      UndirectedGraph g = Graphs.mdlToGraph(mdl);
      triangulate(g);
      jtCurrent = buildJtStructure();
      mdl.setInferenceCache(JunctionTreeInferencer.class, jtCurrent);
    }

    initJtCpts(mdl, jtCurrent);
    return jtCurrent;
  }
 public double dumpLogJoint(Assignment assn) {
   return jtCurrent.dumpLogJoint(assn);
 }
 public double lookupLogJoint(Assignment assn) {
   return jtCurrent.lookupLogJoint(assn);
 }