public static Set<HeadedSyntacticCategory> getSyntacticCategoryClosure(
      Collection<HeadedSyntacticCategory> syntacticCategories) {
    Set<String> featureValues = Sets.newHashSet();
    for (HeadedSyntacticCategory cat : syntacticCategories) {
      getAllFeatureValues(cat.getSyntax(), featureValues);
    }

    // Compute the closure of syntactic categories, assuming the only
    // operations are function application and feature assignment.
    Queue<HeadedSyntacticCategory> unprocessed = new LinkedList<HeadedSyntacticCategory>();
    unprocessed.addAll(syntacticCategories);
    
    Set<HeadedSyntacticCategory> allCategories = Sets.newHashSet();
    while (unprocessed.size() > 0) {
      HeadedSyntacticCategory cat = unprocessed.poll();
      Preconditions.checkArgument(cat.isCanonicalForm());
      
      allCategories.addAll(canonicalizeCategories(cat.getSubcategories(featureValues)));
      
      if (!cat.isAtomic()) {
        HeadedSyntacticCategory ret = cat.getReturnType().getCanonicalForm();
        if (!allCategories.contains(ret) && !unprocessed.contains(ret)) {
          unprocessed.offer(ret);
        }

        HeadedSyntacticCategory arg = cat.getArgumentType().getCanonicalForm();
        if (!allCategories.contains(arg) && !unprocessed.contains(arg)) {
          unprocessed.offer(arg);
        }
      }
    }

    // XXX: jayantk 1/8/2016 I think this loop does exactly the same thing as 
    // the previous one.
    /*
    Set<HeadedSyntacticCategory> allCategories = Sets.newHashSet();
    for (HeadedSyntacticCategory cat : syntacticCategories) {
      Preconditions.checkArgument(cat.isCanonicalForm());
      allCategories.addAll(canonicalizeCategories(cat.getSubcategories(featureValues)));

      while (!cat.getSyntax().isAtomic()) {
        allCategories.addAll(canonicalizeCategories(cat.getArgumentType().getCanonicalForm().getSubcategories(featureValues)));
        allCategories.addAll(canonicalizeCategories(cat.getReturnType().getCanonicalForm().getSubcategories(featureValues)));
        cat = cat.getReturnType();
      }
    }
    */

    return allCategories;
  }
public static Set < HeadedSyntacticCategory > getSyntacticCategoryClosure ( Collection < HeadedSyntacticCategory > syntacticCategories ) { Set < String > featureValues = Sets . newHashSet ( ) ; for ( HeadedSyntacticCategory cat : syntacticCategories ) { getAllFeatureValues ( cat . getSyntax ( ) , featureValues ) ; } Queue < HeadedSyntacticCategory > unprocessed = new LinkedList < HeadedSyntacticCategory > ( ) ; unprocessed . addAll ( syntacticCategories ) ; Set < HeadedSyntacticCategory > allCategories = Sets . newHashSet ( ) ; while ( unprocessed . size ( ) > 0 ) { HeadedSyntacticCategory cat = unprocessed . poll ( ) ; Preconditions . checkArgument ( cat . isCanonicalForm ( ) ) ; allCategories . addAll ( canonicalizeCategories ( cat . getSubcategories ( featureValues ) ) ) ; if ( ! cat . isAtomic ( ) ) { HeadedSyntacticCategory ret = cat . getReturnType ( ) . getCanonicalForm ( ) ; if ( ! allCategories . contains ( ret ) && ! unprocessed . contains ( ret ) ) { unprocessed . offer ( ret ) ; } HeadedSyntacticCategory arg = cat . getArgumentType ( ) . getCanonicalForm ( ) ; if ( ! allCategories . contains ( arg ) && ! unprocessed . contains ( arg ) ) { unprocessed . offer ( arg ) ; } } } return allCategories ; }
Gets the closure of a set of syntactic categories under function
application and feature assignment.

@param syntacticCategories - the categories to get the closure of.
Must be provided in canonical form.

@return closure of the argument categories, in canonical form.