anchor.diff:  
       //
       let private nonfreeItems (graph : ParserStatePositionGraph<'Nonterminal, 'Terminal, 'Lookahead>) =
  +        /// For each item in the graph, contains the set of items/actions reachable from it.
  +        let reachableFrom = LabeledSparseDigraph.reachable graph
  +
  +        /// For each item in the graph, contains the set of items/actions it dominates.
  +        let dominated = LabeledSparseDigraph.dominators graph
  +
           // Positions are not free if they can derive themselves
           // (i.e., if they have a self-loop in the graph).
           let nonfreeItems =
  -            (Set.empty, graph)
  -            ||> Set.fold (fun nonfreePositions (source, target) ->
  -                match target with
  -                | Item target when source = target ->
  -                    Set.add source nonfreePositions
  +            (Set.empty, reachableFrom)
  +            ||> Map.fold (fun nonfreeItems itemOrAction reachable ->
  +                // We only care about items, not actions.
  +                match itemOrAction with
  +                | Item item when Set.contains itemOrAction reachable ->
  +                    Set.add item nonfreeItems
                   | _ ->
  -                    nonfreePositions)
  -
  -        /// For each item in the graph, contains the set of items/actions reachable from it.
  -        let reachableFrom = reachable graph
  -
  -        /// For each item in the graph, contains the set of items/actions it dominates.
  -        let dominated = dominators graph
  -
  -        // TEMP : This is just needed to get the unique set of items/positions in the graph.
  -        // Once we change over to a more efficient graph representation, this won't be needed.
  -        let graphItems =
  -            (Set.empty, graph)
  -            ||> Set.fold (fun graphItems (source, target) ->
  -                match target with
  -                | Item target ->
  -                    graphItems
  -                    |> Set.add source
  -                    |> Set.add target
  -                | Action _ ->
  -                    Set.add source graphItems)
  +                    nonfreeItems)
   
           // For a position to be free, it must be a dominator
           // of every action reachable from it.
  -        (nonfreeItems, graphItems)
  -        ||> Set.fold (fun nonfreeItems item ->
  -            /// The items/actions dominated by this item.
  -            let dominatedItemsAndActions = Map.find item dominated
  -
  -            /// The items/actions reachable from this item.
  -            let reachableItemsAndActions = Map.find item reachableFrom
  -
  -            // Does this item dominate all of the actions reachable from it?
  -            let dominatesAllReachableActions =
  -                reachableItemsAndActions
  -                |> Set.forall (function
  -                    | Item _ -> true
  -                    | (Action _) as action ->
  -                        Set.contains action dominatedItemsAndActions)                    
  +        (nonfreeItems, graph.Vertices)
  +        ||> Set.fold (fun nonfreeItems itemOrAction ->
  +            match itemOrAction with
  +            | Action _ ->
  +                // We only care about items/positions so just ignore actions.
  +                nonfreeItems
  +            | Item item ->
  +                /// The items/actions dominated by this item.
  +                let dominatedItemsAndActions = Map.find itemOrAction dominated
  +
  +                /// The items/actions reachable from this item.
  +                let reachableItemsAndActions = Map.find itemOrAction reachableFrom
  +
  +                // Does this item dominate all of the actions reachable from it?
  +                let dominatesAllReachableActions =
  +                    reachableItemsAndActions
  +                    |> Set.forall (function
  +                        | Item _ ->
  +                            true    // Ignore items here, we only care about actions.
  +                        | (Action _) as action ->
  +                            Set.contains action dominatedItemsAndActions)                    
               
  -            // If not, add this item to the set of non-free items.
  -            if dominatesAllReachableActions then
  -                nonfreeItems
  -            else
  -                Set.add item nonfreeItems)
  +                // If not, add this item to the set of non-free items.
  +                if dominatesAllReachableActions then
  +                    nonfreeItems
  +                else
  +                    Set.add item nonfreeItems)
   
       //
       let ofAugmentedGrammar (grammar : AugmentedGrammar<'Nonterminal, 'Terminal>) =
  
positive.code:     when 'Nonterminal : comparison
      and 'Terminal : comparison
      and 'Lookahead : comparison> =
      Set<LrItem<'Nonterminal, 'Terminal, 'Lookahead> *
          ParserStatePositionGraphNode<'Nonterminal, 'Terminal, 'Lookahead>>
  
  //
  [<RequireQualifiedAccess>]
  module internal FreePositions =
      //
      let private dominators (pspg : ParserStatePositionGraph<'Nonterminal, 'Terminal, 'Lookahead>)
          : Map<LrItem<'Nonterminal, 'Terminal, 'Lookahead>, Set<ParserStatePositionGraphNode<'Nonterminal, 'Terminal, 'Lookahead>>> =
          // TODO
          raise <| System.NotImplementedException "FreePositions.dominators"
  
      //
      let private reachable (pspg : ParserStatePositionGraph<'Nonterminal, 'Terminal, 'Lookahead>)
          : Map<LrItem<'Nonterminal, 'Terminal, 'Lookahead>, Set<ParserStatePositionGraphNode<'Nonterminal, 'Terminal, 'Lookahead>>> =
          // TODO
          raise <| System.NotImplementedException "FreePositions.reachable"
  
      /// Computes the Parser State Position Graph of an LR(0) parser state.
      let private positionGraph (productions : Map<'Nonterminal, Symbol<'Nonterminal, 'Terminal>[][]>) (parserState : Lr0ParserState<'Nonterminal, 'Terminal>)
          : ParserStatePositionGraph<_,_,_> =
          // OPTIMIZE : The code below can be improved slightly (for correctness and speed)
          // by using our Set.mapPartition function.
  
          //
          let transitionItems, actionItems =
  
negative.code:                 | Symbol.Terminal _ ->
                      invalidOp "A terminal was found where a nonterminal was expected."
  
              (positionGraph, parserState)
              ||> Set.fold (fun positionGraph item ->
                  // A derivation edge exists iff the nonterminal produced by this item
                  // is the one we're trying to derive AND the parser position of this
                  // item is the initial position.
                  if item.Nonterminal = derivingNonterminal && item.Position = 0<_> then
                      Graph.addEdge (Item nonterminalDerivingItem) (Item item) () positionGraph
                  else
                      positionGraph))
  
      //
      let private positionGraphs (grammar : AugmentedGrammar<'Nonterminal, 'Terminal>) =
  