nodes: 0, module; 1, function_definition; 2, function_name:have_cycle; 3, parameters; 4, type; 5, block; 6, typed_parameter; 7, identifier:frozenset; 8, expression_statement; 9, comment:# topological sort; 10, expression_statement; 11, comment:# walked nodes; 12, expression_statement; 13, comment:# all nodes of the graph; 14, expression_statement; 15, comment:# succ: preds; 16, expression_statement; 17, while_statement; 18, return_statement; 19, identifier:graph; 20, type; 21, comment:"""Perform a topologic sort to detect any cycle.
  
      Return the set of unsortable nodes. If at least one item,
      then there is cycle in given graph.
  
      """; 22, assignment; 23, assignment; 24, assignment; 25, assignment; 26, comparison_operator:last_walked_len != len(walked); 27, block; 28, call; 29, identifier:dict; 30, identifier:walked; 31, call; 32, identifier:nodes; 33, call; 34, identifier:preds; 35, call; 36, identifier:last_walked_len; 37, unary_operator; 38, identifier:last_walked_len; 39, call; 40, expression_statement; 41, for_statement; 42, identifier:frozenset; 43, argument_list; 44, identifier:set; 45, argument_list; 46, identifier:frozenset; 47, argument_list; 48, identifier:reversed_graph; 49, argument_list; 50, integer:1; 51, identifier:len; 52, argument_list; 53, assignment; 54, identifier:node; 55, binary_operator:nodes - walked; 56, block; 57, binary_operator:nodes - walked; 58, call; 59, identifier:graph; 60, identifier:walked; 61, identifier:last_walked_len; 62, call; 63, identifier:nodes; 64, identifier:walked; 65, if_statement; 66, identifier:nodes; 67, identifier:walked; 68, attribute; 69, argument_list; 70, identifier:len; 71, argument_list; 72, comparison_operator:len(preds.get(node, set()) - walked) == 0; 73, block; 74, identifier:it; 75, identifier:chain; 76, call; 77, call; 78, identifier:walked; 79, call; 80, integer:0; 81, expression_statement; 82, attribute; 83, argument_list; 84, attribute; 85, argument_list; 86, identifier:len; 87, argument_list; 88, call; 89, attribute; 90, identifier:from_iterable; 91, call; 92, identifier:graph; 93, identifier:keys; 94, binary_operator:preds.get(node, set()) - walked; 95, attribute; 96, argument_list; 97, identifier:it; 98, identifier:chain; 99, attribute; 100, argument_list; 101, call; 102, identifier:walked; 103, identifier:walked; 104, identifier:add; 105, identifier:node; 106, identifier:graph; 107, identifier:values; 108, attribute; 109, argument_list; 110, identifier:preds; 111, identifier:get; 112, identifier:node; 113, call; 114, identifier:set; 115, argument_list
code: def have_cycle(graph:dict) -> frozenset:
      """Perform a topologic sort to detect any cycle.
  
      Return the set of unsortable nodes. If at least one item,
      then there is cycle in given graph.
  
      """
      # topological sort
      walked = set()  # walked nodes
      nodes = frozenset(it.chain(it.chain.from_iterable(graph.values()), graph.keys()))  # all nodes of the graph
      preds = reversed_graph(graph)  # succ: preds
      last_walked_len = -1
      while last_walked_len != len(walked):
          last_walked_len = len(walked)
          for node in nodes - walked:
              if len(preds.get(node, set()) - walked) == 0:
                  walked.add(node)
      return frozenset(nodes - walked)