diff --git a/readTrace.py b/readTrace.py index bbf5892f545b4820bea92761b07e1e601bd87a3d..0600ed05d303497e46c06acaf09b253a8e26a4c5 100755 --- a/readTrace.py +++ b/readTrace.py @@ -5,7 +5,7 @@ import argparse ################################################################################ def lenLine() : - return 35 + return 40 ################################################################################ ################################################################################ @@ -57,18 +57,20 @@ class History() : #------------------------------------------------------------------------------- def segmentInBlocks(self) : - # structure : sentence = list of block = list of versions = list of steps + #structure : sentence = [annotations,list of blocks] = list of versions = list of steps sentences = [] - for sentence in self.sentences : + for sentenceAnnot in self.sentences : + annot = sentenceAnnot[0] + sentence = sentenceAnnot[1] lastState = None - sentences.append([]) + sentences.append([annot, []]) blockIndex = 0 for step in sentence : if lastState is not None and lastState != step.state : blockIndex += 1 - while blockIndex >= len(sentences[-1]) : - sentences[-1].append([[]]) - block = sentences[-1][blockIndex][-1] + while blockIndex >= len(sentences[-1][1]) : + sentences[-1][1].append([[]]) + block = sentences[-1][1][blockIndex][-1] block.append(step) lastState = step.state if "BACK" in step.action and "NOBACK" not in step.action : @@ -76,10 +78,10 @@ class History() : backState = step.state while backSize > 0 : blockIndex -= 1 - state = sentences[-1][blockIndex][-1][0].state + state = sentences[-1][1][blockIndex][-1][0].state if state == backState : backSize -= 1 - for block in sentences[-1][blockIndex:] : + for block in sentences[-1][1][blockIndex:] : block.append([]) self.sentences = sentences @@ -88,34 +90,20 @@ class History() : #------------------------------------------------------------------------------- def computeValues(self) : for sentence in self.sentences : - for step in sentence : + for step in sentence[1] : step.distance = abs(step.actionScore-step.oracleScore) step.oracleIndex = [a[1] for a in step.scores].index(step.oracleAction) #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- - def printStats(self, out) : - if type(self.sentences[0][0]) != list : # Before segmentInBlocks - print("%d sentences, %d actions"%(len(self.sentences), - sum([len(s) for s in self.sentences])), file=out) - - for sentence in self.sentences : - print("", file=out) - print(englobStr("Sentence", "-", 2*lenLine()), file=out) - for step in sentence : - print(step, file=out) - return - + def printHumanReadable(self, out) : for sentIndex in range(len(self.sentences)) : - sentence = self.sentences[sentIndex] - print("", file=out) - print(englobStr("Sentence %d"%sentIndex, "-", 2*lenLine()), file=out) + sentence = self.sentences[sentIndex][1] + annotations = [self.sentences[sentIndex][0][wid] for wid in sorted(list(self.sentences[sentIndex][0].keys()))] + maxNbVersions = max([len(block) for block in sentence]) + print(englobStr("Sentence %d"%sentIndex, "-", (1+maxNbVersions)*(1+lenLine())), file=out) + totalOutput = [] for block in sentence : - if type(block[0]) != list : # One version of the block, without backtrack - print(englobStr("State %d"%block[0].state, "-", lenLine()), file=out) - for step in block : - print(step, file=out) - continue versions = [] for version in block : versions.append([]) @@ -125,12 +113,16 @@ class History() : versions[-1].append(str(step) + (lenLine()-len(str(step)))*" ") maxIndex = max([len(version) for version in versions]) for i in range(maxIndex) : - print("\t".join([version[i] for version in versions if i < len(version)])) + totalOutput.append("") + for j in range(maxNbVersions) : + totalOutput[-1] += ("\t" if j > 0 else "") + (versions[j][i] if j in range(len(versions)) and i in range(len(versions[j])) else lenLine()*" ") + for i in range(len(totalOutput)) : + print(totalOutput[i] + ("\t"+("\t".join(annotations[i].split())) if i in range(len(annotations)) else ""), file=out) + print("", file=out) #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- def readFromTrace(self, traceFile) : - self.sentences.append([]) curStep = Step() for line in open(traceFile, "r") : @@ -138,12 +130,18 @@ class History() : # End of sentence : if len(line) == 0 : - if len(self.sentences[-1]) > 0 : + if len(self.sentences) == 0 or len(self.sentences[-1]) > 0 : self.sentences.append([]) + self.sentences[-1].append({}) + self.sentences[-1].append([]) continue if "state :" in line : curStep.state = int(line.split(':')[-1].strip()) + elif "=>" in line : + annotLine = line.split("=>")[-1] + curId = int(annotLine.split()[0]) + self.sentences[-1][0][curId] = annotLine elif "stack :" in line : curStep.stack = ["".join([c for c in a if c.isdigit()]) for a in line.split(':')[-1].strip()[1:-2].split(',')] curStep.stack = [int(a) for a in curStep.stack if len(a) > 0] @@ -161,7 +159,9 @@ class History() : curStep.scores[i-1] = " ".join(curStep.scores[i-1:i+1]) curStep.scores = [a.replace("*","").split(':') for a in curStep.scores if not len(a.split(':')) == 1] curStep.scores = [(float(a[0]), a[1]) for a in curStep.scores] - + elif " " in line : + curId = int(annotLine.split()[0]) + self.sentences[-1][0][curId] = annotLine elif "Chosen action :" in line : curStep.action = line.split(':')[-1].strip() elif "Oracle costs :" in line : @@ -174,7 +174,7 @@ class History() : curStep.oracleScore = [a[0] for a in curStep.scores if a[1] == curStep.oracleAction][0] curStep.actionScore = [a[0] for a in curStep.scores if a[1] == curStep.action][0] - self.sentences[-1].append(curStep) + self.sentences[-1][-1].append(curStep) curStep = Step() #------------------------------------------------------------------------------- ################################################################################ @@ -193,185 +193,6 @@ if __name__ == "__main__" : history.segmentInBlocks() - history.printStats(sys.stdout) + history.printHumanReadable(sys.stdout) ################################################################################ -def trash() : - backSize = 1 # 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 - nbCorrectCorrect = 0 - nbErrCorrect = 0 - nbErrErr = 0 - nbCorrectErr = 0 - - curState = None - curStack = None - curHistory = None - curHistoryPop = None - curScores = None - curAction = None - curCosts = None - curCost = None - curNbUndone = None - curUndone = None - actionsStats = [] - - for line in open(sys.argv[1], "r") : - line = line.strip() - print(line) - - # 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 - curCost = None - curNbUndone = None - curUndone = None - actionsStats = [] - - # 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 "nbUndone :" in line : - curNbUndone = int(line.split(':')[1].strip()) - 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] - curCost = None if "BACK" in curAction else [c[0] for c in curCosts if c[1] == curAction][0] - correctAction = [a[1] for a in curCosts if a[0] == min([b[0] for b in curCosts])][0] - correctActionScore = [a[0] for a in curScores if a[1] == correctAction][0] - chosenActionScore = [a[0] for a in curScores if a[1] == curAction][0] - distanceOfCorrectAction = abs(correctActionScore-chosenActionScore) - indexOfCorrect = [a[1] for a in curScores].index(correctAction) - if "BACK" not in curAction : - if curUndone is None or len(curUndone) == 0 : - actionsStats.append((curAction,correctAction,distanceOfCorrectAction,indexOfCorrect)) - else : - actionsStats[-len(curUndone)] = (curAction,correctAction,distanceOfCorrectAction,indexOfCorrect) - # 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 - - print("curUndone = %s"%str(curUndone)) - print("actionsStats = %s"%str(actionsStats)) - - if curUndone is not None and len(curUndone) > 0 and curNbUndone > 0 and "NOBACK" not in curAction and "BACK" not in curAction : - prevCost = curUndone[0] - curUndone = curUndone[1:] - if prevCost == 0 and curCost == 0 : - nbCorrectCorrect += 1 - elif prevCost == 0 and curCost != 0 : - nbCorrectErr += 1 - elif prevCost != 0 and curCost != 0 : - nbErrErr += 1 - elif prevCost != 0 and curCost == 0 : - nbErrCorrect += 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 curUndone is None : - curUndone = [] - curUndone = [a[1]] + curUndone - 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 = "%5.2f%%"%(100.0*undoErr/total) - print(action) - print(" %s (%d/%d)\tof them canceled a bad action"%(perc, undoErr, total)) - total += nbNoBacks["NOBACK"] - undoErr += nbNoBacksUndoError["NOBACK"] - perc = "%5.2f%%"%(100.0*undoErr/total) - print(" %s (%d/%d)\tif it was always chosen"%(perc, undoErr, total)) - - print("\nAbout error correction after a BACK :") - totalRedo = nbErrErr + nbErrCorrect + nbCorrectErr + nbCorrectCorrect - print(" %5.2f%% (%d/%d)\ttransformed Error into Error"%(100.0*nbErrErr/totalRedo, nbErrErr, totalRedo)) - print(" %5.2f%% (%d/%d)\ttransformed Correct into Correct"%(100.0*nbCorrectCorrect/totalRedo, nbCorrectCorrect, totalRedo)) - print(" %5.2f%% (%d/%d)\ttransformed Correct into Error"%(100.0*nbCorrectErr/totalRedo, nbCorrectErr, totalRedo)) - print(" %5.2f%% (%d/%d)\ttransformed Error into Correct"%(100.0*nbErrCorrect/totalRedo, nbErrCorrect, totalRedo))