code: public static double[] outsideAlgorithm(final Hypergraph graph, final Hyperpotential w, final Semiring s, final double[] beta) {
          final int n = graph.getNodes().size();
          final double[] alpha = new double[n];
          // \alpha_i = 0 \forall i
          Arrays.fill(alpha, s.zero());
          // \alpha_{root} = 1
          alpha[graph.getRoot().getId()] = s.one();
          graph.applyRevTopoSort(new HyperedgeFn() {
              
              @Override
              public void apply(Hyperedge e) {
                  int i = e.getHeadNode().getId();
                  // \forall j \in T(e): 
                  // \alpha_j += \alpha_{H(e)} * w_e * \prod_{k \in T(e) : k \neq j} \beta_k
                  for (Hypernode jNode : e.getTailNodes()) {
                      int j = jNode.getId();
                      double prod = s.one();
                      for (Hypernode kNode : e.getTailNodes()) {
                          int k = kNode.getId();
                          if (k == j) { continue; }
                          prod = s.times(prod, beta[k]);
                      }
                      prod = s.times(prod, alpha[i]);
                      prod = s.times(prod, w.getScore(e, s));
                      alpha[j] = s.plus(alpha[j], prod);
                      //if (log.isTraceEnabled()) { log.trace(String.format("outside: %s w_e=%f prod=%f alpha[%d]=%f", e.getLabel(), w.getScore(e,s), prod, j, alpha[j])); }
                  }
              }
              
          });
          return alpha;
      }
docs: Runs the outside algorithm on a hypergraph.
  
  @param graph The hypergraph
  @param w The potential function.
  @param s The semiring.
  @param beta The beta value for each Hypernode. Where beta[i] is the inside
  score for the i'th node in the Hypergraph, graph.getNodes().get(i).
  @return The alpha value for each Hypernode. Where alpha[i] is the outside
  score for the i'th node in the Hypergraph, graph.getNodes().get(i).