<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _prune_traverse_using_omitted_locations(match_traversal, omitted_locations, complex_optional_roots, location_to_optional_roots):
 """Return a prefix of the given traverse, excluding any blocks after an omitted optional. Given a subset (omitted_locations) of complex_optional_roots, return a new match traversal removing all MatchStep objects that are within any omitted location. Args: match_traversal: list of MatchStep objects to be pruned omitted_locations: subset of complex_optional_roots to be omitted complex_optional_roots: list of all @optional locations (location immmediately preceding an @optional traverse) that expand vertex fields location_to_optional_roots: dict mapping from location -> optional_roots where location is within some number of @optionals and optional_roots is a list of optional root locations preceding the successive @optional scopes within which the location resides Returns: list of MatchStep objects as a copy of the given match traversal with all steps within any omitted location removed. """

    new_match_traversal = []
    for step in match_traversal:
        new_step = step
        if isinstance(step.root_block, Traverse) and step.root_block.optional:
            current_location = step.as_block.location
            optional_root_locations_stack = location_to_optional_roots.get(current_location, None)
            optional_root_location = optional_root_locations_stack[-1]

            if optional_root_location is None:
                raise AssertionError(u'Found optional Traverse location {} that was not present '
                                     u'in location_to_optional_roots dict: {}'
                                     .format(current_location, location_to_optional_roots))
            elif optional_root_location in omitted_locations:
                # Add filter to indicate that the omitted edge(s) shoud not exist
                field_name = step.root_block.get_field_name()
                new_predicate = filter_edge_field_non_existence(LocalField(field_name))
                old_filter = new_match_traversal[-1].where_block
                if old_filter is not None:
                    new_predicate = BinaryComposition(u'&&', old_filter.predicate, new_predicate)
                new_match_step = new_match_traversal[-1]._replace(
                    where_block=Filter(new_predicate))
                new_match_traversal[-1] = new_match_step

                # Discard all steps following the omitted @optional traverse
                new_step = None
            elif optional_root_location in complex_optional_roots:
                # Any non-omitted @optional traverse (that expands vertex fields)
                # becomes a normal mandatory traverse (discard the optional flag).
                new_root_block = Traverse(step.root_block.direction, step.root_block.edge_name)
                new_step = step._replace(root_block=new_root_block)
            else:
                # The current optional traverse is a "simple optional" (one that does not
                # expand vertex fields). No further action is required since MATCH supports it.
                pass

        # If new_step was set to None,
        # we have encountered a Traverse that is within an omitted location.
        # We discard the remainder of the match traversal (everything following is also omitted).
        if new_step is None:
            break
        else:
            new_match_traversal.append(new_step)

    return new_match_traversal