anchor.diff:              pMatrix |> Map.iter (fun nts _ -> completeOnePair nts)
           
           let rec completeSubLayer layer matricesSize = 
  -            if matricesSize = 1 then
  -                let headsFromTail (tail, tailProb) = 
  -                    if complexRules.ContainsKey tail then 
  -                        complexRules.Item tail |> List.map (fun (head, headProb) -> head, headProb * tailProb)
  -                    else 
  -                        []
  -
  -                let tails row col = pMatrix |> Map.map (fun _ probs -> probs.[row, col-1]) |> Map.filter (fun _ prob -> prob > 0.)
  -                let heads (row, col) = tails row col |> Map.toList |> List.map headsFromTail |> List.concat
  -
  -                layer 
  -                |> Array.map (fun (matrix: SubMatrix.T) -> matrix.Top)
  -                |> Array.map (fun top -> top, heads top)
  -                |> Array.iter (fun (top, heads) -> heads |> updateTMatrixCell (fst top) (snd top - 1))
  -
  -            else
  +            if Array.length layer > 0 
  +            then
  +                if matricesSize = 1 then
  +                    let headsFromTail (tail, tailProb) = 
  +                        if complexRules.ContainsKey tail then 
  +                            complexRules.Item tail |> List.map (fun (head, headProb) -> head, headProb * tailProb)
  +                        else 
  +                            []
  +
  +                    let tails row col = pMatrix |> Map.map (fun _ probs -> probs.[row, col-1]) |> Map.filter (fun _ prob -> prob > 0.)
  +                    let heads (row, col) = tails row col |> Map.toList |> List.map headsFromTail |> List.concat
  +
  +                    layer 
  +                    |> Array.map (fun (matrix: SubMatrix.T) -> matrix.Top)
  +                    |> Array.map (fun top -> top, heads top)
  +                    |> Array.iter (fun (top, heads) -> heads |> updateTMatrixCell (fst top) (snd top - 1))
  +
  +                else
  +                    let halfMatricesSize = int(matricesSize / 2)
  +                    let zeroSubLayer = layer |> Array.map (fun (matrix: SubMatrix.T) -> matrix.BottomMatrix)        
  +                    completeSubLayer zeroSubLayer halfMatricesSize
  +                    completeVLayer layer matricesSize
  +
  +        and completeVLayer layer matricesSize = 
  +            if Array.length layer > 0 
  +            then
                   let halfMatricesSize = int(matricesSize / 2)
  -                let zeroSubLayer = layer |> Array.map (fun (matrix: SubMatrix.T) -> matrix.BottomMatrix)        
  -                completeSubLayer zeroSubLayer halfMatricesSize
  -                completeVLayer layer matricesSize
  -
  -        and completeVLayer layer matricesSize = 
  -            let halfMatricesSize = int(matricesSize / 2)
  -
  -            let firstSubLayerLeft = 
  -                layer 
  -                |> Array.map (fun matrix -> matrix.LeftMatrix)
  -            let firstSubLayerRight = 
  -                layer 
  -                |> Array.map (fun matrix -> matrix.RightMatrix)
  -
  -            let toMultLeft = 
  -                firstSubLayerLeft 
  -                |> Array.map (fun matrix -> matrix.RelativeMatrix 0 -(snd matrix.Top - fst matrix.Top - matricesSize), 
  -                                            matrix.RelativeMatrix halfMatricesSize 0)
  -            let toMultRight = 
  -                firstSubLayerRight 
  -                |> Array.map (fun matrix -> matrix.RelativeMatrix 0 -halfMatricesSize, 
  -                                            matrix.RelativeMatrix (snd matrix.Top - fst matrix.Top - matricesSize) 0)
  -
  -            let firstSubLayer = Array.append firstSubLayerLeft firstSubLayerRight
  -            let toMult = Array.append toMultLeft toMultRight
  +                let reducedLayer = 
  +                    if snd layer.[Array.length layer - 1].Top > stringSize + 1 
  +                    then layer.[0..Array.length layer - 2] 
  +                    else layer
  +
  +                let firstSubLayer = 
  +                    if Array.length layer = Array.length reducedLayer
  +                    then
  +                        layer 
  +                        |> Array.collect (fun matrix -> [|matrix.LeftMatrix; matrix.RightMatrix|])
  +                    else
  +                        let reducedMatrix = layer.[Array.length layer - 1]
  +                        let allButOne = 
  +                            reducedLayer 
  +                            |> Array.collect (fun matrix -> [|matrix.LeftMatrix; matrix.RightMatrix|])
  +                        Array.append allButOne [| reducedMatrix.LeftMatrix |]   
  +
  +                let toMult = 
  +                    //todo: annotation?
  +                    let getMults i (matrix: SubMatrix.T) =
  +                        if (i % 2) = 1
  +                        then
  +                            matrix.RelativeMatrix 0 -(snd matrix.Top - fst matrix.Top - matricesSize), 
  +                            matrix.RelativeMatrix halfMatricesSize 0
  +                        else
  +                            matrix.RelativeMatrix 0 -halfMatricesSize, 
  +                            matrix.RelativeMatrix (snd matrix.Top - fst matrix.Top - matricesSize) 0
  +                    firstSubLayer
  +                    |> Array.mapi getMults
                            
  -            let firstMultTasks = Array.map2 (fun w (f1, f2) -> {where=w; from1=f1; from2=f2})
  -                                            firstSubLayer 
  -                                            toMult
  +                let firstMultTasks = Array.map2 (fun w (f1, f2) -> {where=w; from1=f1; from2=f2})
  +                                                firstSubLayer 
  +                                                toMult
                                               
  -            firstMultTasks |> Array.iter performMultiplication
  -            completeSubLayer firstSubLayer halfMatricesSize
  +                firstMultTasks |> Array.iter performMultiplication
  +                completeSubLayer firstSubLayer halfMatricesSize
                         
  -            let secondSubLayer = 
  -                layer 
  -                |> Array.map (fun matrix -> matrix.TopMatrix)
  -            let secondToMult = 
  -                secondSubLayer 
  -                |> Array.map (fun matrix -> matrix.RelativeMatrix 0 -(snd matrix.Top - fst matrix.Top - matricesSize), 
  -                                            matrix.RelativeMatrix halfMatricesSize 0) 
  -            let thirdToMult = 
  -                secondSubLayer 
  -                |> Array.map (fun matrix -> matrix.RelativeMatrix 0 -halfMatricesSize, 
  -                                            matrix.RelativeMatrix (snd matrix.Top - fst matrix.Top - matricesSize) 0)
  -            let secondMultTasks = Array.map2 (fun w (f1, f2) -> {where=w; from1=f1; from2=f2}) secondSubLayer secondToMult 
  -            let thirdMultTasks = Array.map2 (fun w (f1, f2) -> {where=w; from1=f1; from2=f2}) secondSubLayer thirdToMult 
  +                let secondSubLayer =                 
  +                    reducedLayer 
  +                    |> Array.map (fun matrix -> matrix.TopMatrix)
  +                let secondToMult = 
  +                    secondSubLayer 
  +                    |> Array.map (fun matrix -> matrix.RelativeMatrix 0 -(snd matrix.Top - fst matrix.Top - matricesSize), 
  +                                                matrix.RelativeMatrix halfMatricesSize 0) 
  +                let thirdToMult = 
  +                    secondSubLayer 
  +                    |> Array.map (fun matrix -> matrix.RelativeMatrix 0 -halfMatricesSize, 
  +                                                matrix.RelativeMatrix (snd matrix.Top - fst matrix.Top - matricesSize) 0)
  +                let secondMultTasks = Array.map2 (fun w (f1, f2) -> {where=w; from1=f1; from2=f2}) secondSubLayer secondToMult 
  +                let thirdMultTasks = Array.map2 (fun w (f1, f2) -> {where=w; from1=f1; from2=f2}) secondSubLayer thirdToMult 
                           
  -            secondMultTasks |> Array.iter performMultiplication
  -            thirdMultTasks  |> Array.iter performMultiplication          
  -            completeSubLayer secondSubLayer halfMatricesSize
  +                secondMultTasks |> Array.iter performMultiplication
  +                thirdMultTasks  |> Array.iter performMultiplication          
  +                completeSubLayer secondSubLayer halfMatricesSize
   
   
           and completeLayer layerNum = 
  
positive.code:         tMatrix.Item S
  
  
  
      [<EntryPoint>]
      let main args = 
          let A = NonTerminal "A"
          let B = NonTerminal "B"
          let BB = NonTerminal "BB"
  
negative.code:             assert (isAnswerValid toCheck (String.length str) searchLen)
              printMatrix toCheck (String.length str) searchLen
              
          check "aabb"
          check "abb"    
          check "aaabbcc"
          check "baaabbcc"
          check "aaaabbcc"
  
          System.Console.ReadLine() |> ignore
          0