     @maxPopulation = 1024
     @maxSize = 100
     @symmetries = ruleSpatialSymmetries rule
-
-  registerResult: (pattern, result, mainKey) ->
-      #Register a pattern with given result, under all keys
-      pattern2result = @pattern2result
-      pattern2result[mainKey] = result
-      for tfm in @symmetries
-        transformedKey = patternKey Cells.transform pattern, tfm
-        if transformedKey isnt mainKey
-          #assert that key either not present, or refers the same result
-          #if pattern2result[transformedKey]?
-          #  
-          pattern2result[transformedKey] = result
-
+    @frozen = false
+    @doubleHitCount = 0
+    @currentPatternKeys = []
+
+  freeze: ->
+    @frozen = true
+    @truncateTable
+
+  stashKeys: (pattern, mainKey) ->
+    keys = @currentPatternKeys
+    keys.push mainKey
+    for tfm in @symmetries
+      transformedKey = patternKey Cells.transform pattern, tfm
+      keys.push transformedKey
+    return
+    
+  writeResult: (result) ->
+    pattern2result = @pattern2result
+    for key in @currentPatternKeys
+      pattern2result[key] = result
+    @currentPatternKeys = []
+    return
 
   analyse: (pattern) ->
     result = @_analyse pattern
     result.hits += 1
+    if result.hits is 2
+      @doubleHitCount += 1
     return result
 
   _analyse: (pattern) -> #result

      key = patternKey curPattern
      #Maybe, we already had this value?
      if (knownResult = @pattern2result[key])?
        #Make current result to point to the cached one.
        if knownResult.resolution isnt null
          #console.log "#### known result:"+JSON.stringify(knownResult)
          return (result.refersTo = unwrapResult knownResult)
      else
        #previously unknown pattern. Register its result (not yet calculated)
        @registerResult curPattern, result, key

      #maybe, analysis has finished?
      if Cells.areEqual pattern, curPattern
        return @makePeriodFoundResult result, dx, dy, iter, bestPatternSearch.getArg()

      #no cycle. Fine.
      bestPatternSearch.put curPattern
      if curPattern.length > maxPopulation
        return @makePatternTooBigResult result
      if Math.max( bounds[2]-bounds[0], bounds[3]-bounds[1]) > maxSize
        return @makePatternToWideResult result

    #After the given number of iterations, nothing was found.
    #Give up.
    @makeCycleNotFoundResult result

  makePeriodFoundResult: (result, dx, dy, period, bestPattern)->
    #console.log "#### period found"
    [bestPattern, result.dx, result.dy] =
         Cells.canonicalize_spaceship bestPattern, @rule, dx, dy
    result.resolution = Resolution.HAS_PERIOD
    result.period = period
    result.cells = bestPattern
    result.hits = 0
    return result

  makePatternToWideResult: (result)->
    #console.log "#### pattern too wide"
    result.resolution = Resolution.TOO_WIDE
    result

  makePatternTooBigResult: (result)->   
    #console.log "#### pattern too big"
    result.resolution = Resolution.OVERPOPUPATION
    result.hits = 0
    result
  makeCycleNotFoundResult: (result)->
    #console.log "#### no cycle found"
    result.resolution = Resolution.NO_PERIOD
    result.hits = 0
    result


  #Truncate memo table to the given number of records, removing items with the least hit count
  truncateTable: (maxRecords) ->
    if maxRecords < 0
      throw new Error "Number of records must be positive"
    pattern2result = @pattern2result
    keysWithHits = ([unwrapResult(result).hits, key] for key, result of pattern2result)
    #sort keys by hit count, more hits go first
    keysWithHits.sort (kh1, kh2) -> kh2[0]-kh1[0]
    #remove the rest keys

    Cells.sortXY pattern
    key = patternKey pattern
    if (result = @pattern2result[key])?
      #console.log "#### FIrst hit!"
      return result
    else
      @stashKeys pattern, key
                
    bestPatternSearch = new Maximizer Cells.energy
    bestPatternSearch.put pattern
