diff --git a/readTrace.py b/readTrace.py
new file mode 100755
index 0000000000000000000000000000000000000000..13df317b7f7c8c331d79a45b67c42884b1d77778
--- /dev/null
+++ b/readTrace.py
@@ -0,0 +1,133 @@
+#! /usr/bin/env python3
+
+import sys
+
+if len(sys.argv) != 2 :
+  print("USAGE : %s trace.txt"%sys.argv[0], file=sys.stderr)
+  exit(1)
+
+backSize = 2 # Script only works with one back action at the moment
+
+nbActionsPerState = {} # for each state, a dict of actionName -> nbOccurences
+nbBacks = {} # dict of backName -> nbOccurences
+nbBacksUndoError = {} # dict of backName -> nb times it has undone at least 1 err
+nbNoBacks = {} # dict of NOBACK -> nbOccurences
+nbNoBacksUndoError = {} # dict of NOBACK -> nb times BACK would have undone at least an error if BACK was always chosen
+
+curState = None
+curStack = None
+curHistory = None
+curHistoryPop = None
+curScores = None
+curAction = None
+curCosts = None
+
+for line in open(sys.argv[1], "r") :
+  line = line.strip()
+
+  # End of sentence :
+  if len(line) == 0 and curHistoryPop is not None :
+    curState = None
+    curStack = None
+    curHistory = None
+    curHistoryPop = None
+    curScores = None
+    curAction = None
+    curCosts = None
+
+  # Collect info on current line :
+  if "state :" in line :
+    curState = int(line.split(':')[-1].strip())
+  elif "stack :" in line :
+    curStack = ["".join([c for c in a if c.isdigit()]) for a in line.split(':')[-1].strip()[1:-2].split(',')]
+    curStack = [int(a) for a in curStack if len(a) > 0]
+  elif "historyPop" in line :
+    curHistoryPop = ":".join(line.replace("'","").split(':')[1:]).split(')')
+    curHistoryPop = [a.split('(')[-1] for a in curHistoryPop if len(a.split(',')) > 1]
+    if len(curHistoryPop) > 0 :
+      curHistoryPop = [(a.split(',')[0].strip(),int(a.split(',')[3].strip().split(':')[-1])) for a in curHistoryPop]
+  elif "history" in line :
+    curHistory = ["".join([c for c in a.strip() if c != "'"]) for a in line.split(':')[-1].strip()[1:-2].split(',')]
+  elif "*" in line :
+    curScores = line.split()
+    for i in range(len(curScores))[::-1] :
+      if len(curScores[i].split(':')) == 1 :
+        curScores[i-1] = " ".join(curScores[i-1:i+1])
+    curScores = [a.replace("*","").split(':') for a in curScores if not len(a.split(':')) == 1]
+    curScores = [(float(a[0]), a[1]) for a in curScores]
+  elif "Chosen action :" in line :
+    curAction = line.split(':')[-1].strip()
+  elif "Oracle costs :" in line :
+    curCosts = line.split(':')[-1].strip().split('[')
+    curCosts = [a[:-1].replace("'","").replace(']','').split(',') for a in curCosts if ',' in a]
+    curCosts = [(int(a[0]), a[1].strip()) for a in curCosts]
+    # End of action choice :
+    # Count actions
+    if curState not in nbActionsPerState :
+      nbActionsPerState[curState] = {}
+    if curAction not in nbActionsPerState[curState] :
+      nbActionsPerState[curState][curAction] = 0
+    nbActionsPerState[curState][curAction] += 1
+    if "NOBACK" in curAction and len([a for a in curHistoryPop if a[0] == "NOBACK"]) >= backSize and "BACK" not in curHistory[-1] :
+      if curAction not in nbNoBacks :
+        nbNoBacks[curAction] = 0
+      nbNoBacks[curAction] += 1
+      size = backSize
+      nbErrors = 0
+      for a in curHistoryPop[::-1] :
+        if a[0] == "NOBACK" :
+          size -= 1
+          if size == 0 :
+            break
+          continue
+        if a[1] < 0 :
+          nbErrors += 1
+      if curAction not in nbNoBacksUndoError :
+        nbNoBacksUndoError[curAction] = 0
+      if nbErrors > 0 :
+        nbNoBacksUndoError[curAction] += 1
+    elif "BACK" in curAction and "NOBACK" not in curAction :
+      if curAction not in nbBacks :
+        nbBacks[curAction] = 0
+      nbBacks[curAction] += 1
+      size = int(curAction.split()[-1].strip())
+      if size != backSize :
+        raise Exception("backSize is wrong")
+      nbErrors = 0
+      for a in curHistoryPop[::-1] :
+        if a[0] == "NOBACK" :
+          size -= 1
+          if size == 0 :
+            break
+          continue
+        if a[1] < 0 :
+          nbErrors += 1
+      if curAction not in nbBacksUndoError :
+        nbBacksUndoError[curAction] = 0
+      if nbErrors > 0 :
+        nbBacksUndoError[curAction] += 1
+
+
+# Printing for each states, number of occurrences of each actions
+print("Occurrences of actions :")
+for state in nbActionsPerState :
+  print("State", state, ":")
+  print("  %d\ttotal"%(sum(list(nbActionsPerState[state].values()))))
+  actions = sorted([[nbActionsPerState[state][action],action] for action in nbActionsPerState[state]])[::-1]
+  actions = ["  %d\t%s"%(a[0],a[1]) for a in actions]
+  print("\n".join(actions))
+
+# Answering the question of whether or not the backs are triggered to undo errors
+# We compare the number of times a back has undone at least 1 bad action
+# with the number of times it would have been the case if we always did back.
+print("\nAbout triggering of back actions :")
+for action in nbBacks :
+  total = nbBacks[action]
+  undoErr = nbBacksUndoError[action]
+  perc = "%.2f%%"%(100.0*undoErr/total)
+  print(action)
+  print("  %s of them canceled a bad action"%perc)
+  total += nbNoBacks["NOBACK"]
+  undoErr += nbNoBacksUndoError["NOBACK"]
+  perc = "%.2f%%"%(100.0*undoErr/total)
+  print("  %s if it was always chosen"%perc)