private static Map<UnaryRule, List<String>> computeUnaryClosure(Collection<UnaryRule> unaryRules) {

      Map<UnaryRule, String> intermediateStates = new HashMap<UnaryRule, String>();
      Counter<UnaryRule> pathCosts = new Counter<UnaryRule>();
      Map<String, List<UnaryRule>> closedUnaryRulesByChild = new HashMap<String, List<UnaryRule>>();
      Map<String, List<UnaryRule>> closedUnaryRulesByParent = new HashMap<String, List<UnaryRule>>();

      Set<String> states = new HashSet<String>();

      for (UnaryRule unaryRule : unaryRules) {
        relax(pathCosts, intermediateStates, closedUnaryRulesByChild, closedUnaryRulesByParent, unaryRule, null, unaryRule.getScore());
        states.add(unaryRule.getParent());
        states.add(unaryRule.getChild());
      }

      for (String intermediateState : states) {
        List<UnaryRule> incomingRules = closedUnaryRulesByChild.get(intermediateState);
        List<UnaryRule> outgoingRules = closedUnaryRulesByParent.get(intermediateState);
        if (incomingRules == null || outgoingRules == null) continue;
        for (UnaryRule incomingRule : incomingRules) {
          for (UnaryRule outgoingRule : outgoingRules) {
            UnaryRule rule = new UnaryRule(incomingRule.getParent(), outgoingRule.getChild());
            double newScore = pathCosts.getCount(incomingRule) * pathCosts.getCount(outgoingRule);
            relax(pathCosts, intermediateStates, closedUnaryRulesByChild, closedUnaryRulesByParent, rule, intermediateState, newScore);
          }
        }
      }

      for (String state : states) {
        UnaryRule selfLoopRule = new UnaryRule(state, state);
        relax(pathCosts, intermediateStates, closedUnaryRulesByChild, closedUnaryRulesByParent, selfLoopRule, null, 1.0);
      }

      Map<UnaryRule, List<String>> closureMap = new HashMap<UnaryRule, List<String>>();

      for (UnaryRule unaryRule : pathCosts.keySet()) {
        unaryRule.setScore(pathCosts.getCount(unaryRule));
        List<String> path = extractPath(unaryRule, intermediateStates);
        closureMap.put(unaryRule, path);
      }

      System.out.println("SIZE: " + closureMap.keySet().size());

      return closureMap;

    }