def compute_schema_edges(
    graph,
    with_node_types = False
):
  """Compute SCHEMA_* edges from the encoded graph.

  We extract the outgoing edges that the automaton sees, but remove the sentinel
  "missing" edges. Incoming edges are redundant and less informative so they
  are not included.

  Args:
    graph: Automaton graph to use.
    with_node_types: Whether to include the node type of the source node.

  Returns:
    List of schema edges.
  """
  result = []
  for source_node_id, node_info in graph.items():
    for out_type, destinations in node_info.out_edges.items():
      for in_tagged_node in destinations:
        if not in_tagged_node.in_edge.endswith("_missing"):
          if with_node_types:
            edge_type = f"SCHEMA_{out_type}_FROM_{node_info.node_type}"
            result.append((source_node_id, in_tagged_node.node_id, edge_type))
          else:
            edge_type = f"SCHEMA_{out_type}"
            result.append((source_node_id, in_tagged_node.node_id, edge_type))

  return result