class DifferentialReachabilityAnswerer extends Answerer {

  @VisibleForTesting
  DifferentialReachabilityParameters parameters(
      NetworkSnapshot snapshot, NetworkSnapshot reference) {
    DifferentialReachabilityQuestion question = (DifferentialReachabilityQuestion) _question;
    PacketHeaderConstraints headerConstraints = question.getHeaderConstraints();
    SpecifierContext snapshotCtxt = _batfish.specifierContext(snapshot);
    SpecifierContext referenceCtxt = _batfish.specifierContext(reference);

    PathConstraints pathConstraints = createPathConstraints(question.getPathConstraints());

    // forbiddenTransitNodes can be different in each snapshot. flow must not transit any
    Set<String> forbiddenTransitNodes =
        Sets.union(
            pathConstraints.getForbiddenLocations().resolve(snapshotCtxt),
            pathConstraints.getForbiddenLocations().resolve(referenceCtxt));

    // requiredTransitNodes can be different in each snapshot. flow must transit any one
    Set<String> requiredTransitNodes =
        Sets.union(
            pathConstraints.getTransitLocations().resolve(snapshotCtxt),
            pathConstraints.getTransitLocations().resolve(referenceCtxt));

    // only consider startLocations that are present+active in both snapshots
    Set<Location> startLocations =
        Sets.intersection(
            resolveActiveLocations(pathConstraints.getStartLocation(), snapshotCtxt),
            resolveActiveLocations(pathConstraints.getStartLocation(), referenceCtxt));
    if (startLocations.isEmpty()) {
      throw new BatfishException(
          "no matching startLocation is present and active in both snapshots");
    }

    // finalNodes can be different in each snapshot
    Set<String> finalNodes =
        Sets.union(
            pathConstraints.getEndLocation().resolve(snapshotCtxt),
            pathConstraints.getEndLocation().resolve(referenceCtxt));

    // TODO generate better IpSpaceAssignments for differential context
    IpSpaceAssignment ipSpaceAssignment =
        SpecifierFactories.getIpSpaceSpecifierOrDefault(
                headerConstraints.getSrcIps(), InferFromLocationIpSpaceSpecifier.INSTANCE)
            .resolve(startLocations, snapshotCtxt);
    IpSpace dstIps =
        firstNonNull(
            AclIpSpace.union(
                SpecifierFactories.getIpSpaceSpecifierOrDefault(
                        headerConstraints.getDstIps(), InferFromLocationIpSpaceSpecifier.INSTANCE)
                    .resolve(ImmutableSet.of(), snapshotCtxt).getEntries().stream()
                    .map(Entry::getIpSpace)
                    .collect(ImmutableList.toImmutableList())),
            UniverseIpSpace.INSTANCE);

    AclLineMatchExpr headerSpace =
        PacketHeaderConstraintsUtil.toAclLineMatchExpr(
            headerConstraints, UniverseIpSpace.INSTANCE, dstIps);

    return new DifferentialReachabilityParameters(
        ReachabilityParameters.filterDispositions(question.getActions().getDispositions()),
        forbiddenTransitNodes,
        finalNodes,
        headerSpace,
        question.getIgnoreFilters(),
        question.getInvertSearch(),
        ipSpaceAssignment,
        question.getMaxTraces(),
        requiredTransitNodes);
  }

  public  DifferentialReachabilityAnswerer(Question question, IBatfish batfish);

}