/**
   * Applies this dependency structure with another, adding any new dependencies
   * to @newResolvedDependencies
   */
  public DependencyStructure compose(
      DependencyStructure other, final List<UnlabelledDependency> newResolvedDependencies) {

    other = other.standardizeApart(coindexation.getMaxID() + 1);
    final UnifyingSubstitution substitution =
        UnifyingSubstitution.make(coindexation.right, other.coindexation.left, false);

    final Set<UnresolvedDependency> newUnresolvedDependencies = new HashSet<>();
    updateResolvedDependencies(
        other, substitution, newUnresolvedDependencies, newResolvedDependencies);

    final Coindexation newCoindexationLeft = substitution.applyTo(coindexation.left);
    final Coindexation newCoindexationRight = substitution.applyTo(other.coindexation.right);
    final boolean headIsLeft = !coindexation.left.idOrHead.equals(coindexation.right.idOrHead);
    final Coindexation.IDorHead idOrHead =
        substitution.applyTo(headIsLeft ? coindexation : other.coindexation).idOrHead;

    final Set<UnresolvedDependency> normalizedUnresolvedDependencies =
        new HashSet<>(newUnresolvedDependencies.size());
    final Coindexation normalizedCoindexation =
        normalize(
            new Coindexation(newCoindexationLeft, newCoindexationRight, idOrHead),
            newUnresolvedDependencies,
            normalizedUnresolvedDependencies,
            newResolvedDependencies,
            1);

    return new DependencyStructure(normalizedCoindexation, normalizedUnresolvedDependencies);
  }
  /** Generalized forward composition (to degree 2) */
  public DependencyStructure compose2(
      DependencyStructure other, final List<UnlabelledDependency> newResolvedDependencies) {
    // A/B (B/C)/D ---> (A/C)/D
    other = other.standardizeApart(coindexation.getMaxID() + 1);

    final UnifyingSubstitution substitution =
        UnifyingSubstitution.make(coindexation.right, other.coindexation.left.left, false);

    final Set<UnresolvedDependency> newUnresolvedDependencies = new HashSet<>();

    updateResolvedDependencies(
        other, substitution, newUnresolvedDependencies, newResolvedDependencies);
    final Set<UnresolvedDependency> normalizedUnresolvedDependencies =
        new HashSet<>(newUnresolvedDependencies.size());
    final Coindexation normalizedCoindexation;
    if (coindexation.isModifier()) {
      // X/X X/Y/Z
      normalizedCoindexation =
          normalize(
              substitution.applyTo(other.coindexation),
              newUnresolvedDependencies,
              normalizedUnresolvedDependencies,
              newResolvedDependencies,
              1);
    } else {
      // S\NP/NP NP/PP/PP
      final Coindexation leftWithSubstitution = substitution.applyTo(coindexation);
      final Coindexation rightWithSubstitution = substitution.applyTo(other.coindexation);
      normalizedCoindexation =
          normalize(
              new Coindexation(
                  new Coindexation(
                      leftWithSubstitution.left,
                      rightWithSubstitution.left.right,
                      leftWithSubstitution.idOrHead),
                  rightWithSubstitution.right,
                  leftWithSubstitution.idOrHead),
              newUnresolvedDependencies,
              normalizedUnresolvedDependencies,
              newResolvedDependencies,
              1);
    }

    return new DependencyStructure(normalizedCoindexation, normalizedUnresolvedDependencies);
  }
 public DependencyStructure conjunction() {
   final Set<UnresolvedDependency> newUnresolvedDependencies = new HashSet<>();
   final Set<UnresolvedDependency> normalizedUnresolvedDependencies =
       new HashSet<>(newUnresolvedDependencies.size());
   final UnifyingSubstitution substitution =
       new UnifyingSubstitution(
           Collections.EMPTY_MAP,
           Collections.EMPTY_MAP,
           Collections.singletonMap(coindexation.getID().head, new Coindexation.IDorHead(-1)));
   Coindexation newCo =
       new Coindexation(coindexation, substitution.applyTo(coindexation), coindexation.idOrHead);
   newCo =
       normalize(
           newCo,
           newUnresolvedDependencies,
           normalizedUnresolvedDependencies,
           Collections.EMPTY_LIST,
           1);
   return new DependencyStructure(newCo, newUnresolvedDependencies, true);
 }
  private static void updateDependencies(
      final DependencyStructure other,
      final UnifyingSubstitution substitution,
      final Set<UnresolvedDependency> newUnresolvedDependencies,
      final List<UnlabelledDependency> newResolvedDependencies) {
    for (final UnresolvedDependency dep : other.unresolvedDependencies) {
      final Dependency updated = substitution.applyTo(dep);

      if (updated.isResolved()) {
        newResolvedDependencies.add((UnlabelledDependency) updated);
      } else {
        newUnresolvedDependencies.add((UnresolvedDependency) updated);
      }
    }
  }
  /**
   * Applies this dependency structure to another, adding any new dependencies
   * to @newResolvedDependencies
   */
  public DependencyStructure apply(
      DependencyStructure other, final List<UnlabelledDependency> newResolvedDependencies) {
    other = other.standardizeApart(coindexation.getMaxID() + 1);

    final UnifyingSubstitution substitution =
        UnifyingSubstitution.make(coindexation.right, other.coindexation, isConjunction);

    final Set<UnresolvedDependency> newUnresolvedDependencies = new HashSet<>();
    final Coindexation newCoindexation = substitution.applyTo(coindexation.left);
    updateResolvedDependencies(
        other, substitution, newUnresolvedDependencies, newResolvedDependencies);

    final Set<UnresolvedDependency> normalizedUnresolvedDependencies =
        new HashSet<>(newUnresolvedDependencies.size());

    final Coindexation normalizedCoindexation =
        normalize(
            newCoindexation,
            newUnresolvedDependencies,
            normalizedUnresolvedDependencies,
            newResolvedDependencies,
            1);
    return new DependencyStructure(normalizedCoindexation, normalizedUnresolvedDependencies);
  }