Report from analyzing the tuner
[satune.git] / src / analyzer / tunerloganalyzer.py
1 import re
2 import argparse
3 import sys
4 import os
5 import plot as pl
6
7 class AutoTunerArgParser:
8         def __init__(self):
9                 self.parser = argparse.ArgumentParser(description='Parsing the output log of the CSolver auto tuner ...')
10                 self.parser.add_argument('--folder', '-f', metavar='bin', type=str, nargs=1,help='output log of running the autotuner ...')
11                 self.parser.add_argument('--number', '-n', metavar='122', type=int, nargs=1,help='Number of runs ...')
12                 self.args = self.parser.parse_args()
13
14         def getFolder(self):
15                 return self.args.folder[0]
16
17         def getRunNumber(self):
18                 return self.args.number[0]
19
20 TUNABLEHEADER = ["DECOMPOSEORDER", "MUSTREACHGLOBAL", "MUSTREACHLOCAL", "MUSTREACHPRUNE", "OPTIMIZEORDERSTRUCTURE",
21                 "ORDERINTEGERENCODING", "PREPROCESS", "NODEENCODING", "EDGEENCODING", "MUSTEDGEPRUNE", "ELEMENTOPT",
22                 "ENCODINGGRAPHOPT", "ELEMENTOPTSETS", "PROXYVARIABLE", "MUSTVALUE", "NAIVEENCODER", "VARIABLEORDER",
23                 "PROBLEM","SATTIME", "EXECTIME","TUNERNUMBER"]
24
25 configs = {"EXECTIME": "-",
26                 "SATTIME":"-",
27                 "TESTCASE":"-",
28                 "PREPROCESS" : "-",
29                 "ELEMENTOPT" : "-",
30                 "ELEMENTOPTSETS" : "-",
31                 "PROXYVARIABLE" : "-",
32                 "#SubGraph" : "-",
33                 "NODEENCODING" : "-",
34                 "EDGEENCODING" : "-",
35                 "NAIVEENCODER" :"-",
36                 "ENCODINGGRAPHOPT" : "-"
37                 }
38
39 REGEXES = {"EXECTIME": "CSOLVER solve time: (.*)",
40                 "SATTIME":"SAT Solving time: (.*)",
41                 "TESTCASE": "deserializing (.+) ...",
42                 "PREPROCESS" : "Param PREPROCESS = (.*)range=\[0,1\]",
43                 "ELEMENTOPT" : "Param ELEMENTOPT = (.*)range=\[0,1\]",
44                 "ELEMENTOPTSETS" : "Param ELEMENTOPTSETS = (.*)range=\[0,1\]",
45                 "PROXYVARIABLE" : "Param PROXYVARIABLE = (.*)range=\[1,5\]",
46                 "#SubGraph" : "#SubGraph = (.*)",
47                 "NODEENCODING" : "Param NODEENCODING = (.*)range=\[0,3\](.*)",
48                 "EDGEENCODING" : "Param EDGEENCODING = (.*)range=\[0,2\](.*)",
49                 "NAIVEENCODER" : "Param NAIVEENCODER = (.*)range=\[1,3\](.*)",
50                 "ENCODINGGRAPHOPT" : "Param ENCODINGGRAPHOPT = (.*)range=\[0,1\]"
51                 }
52
53 def printHeader(file):
54         global TUNABLEHEADER
55         mystr=""
56         for header in TUNABLEHEADER:
57                  mystr+=str(header)+","
58         print >>file, mystr
59
60 def dump(file, row):
61         global TUNABLEHEADER
62         mystr=""
63         data = []
64         for i in range(len(TUNABLEHEADER)):
65                 mystr += row[TUNABLEHEADER[i]]+ ","
66                 data.append(row[TUNABLEHEADER[i]])
67         print ("mystr is:"+ mystr)
68         print >>file, mystr
69         return data
70
71 def loadTunerInfo(row, filename):
72         with open(filename) as f:
73                 for line in f:
74                         numbers = re.findall('\d+',line)
75                         numbers = map(int,numbers)
76                         row[TUNABLEHEADER[numbers[3]]] = row[TUNABLEHEADER[numbers[3]]] + str(numbers[7])
77
78 def loadSolverTime(row, filename):
79         global REGEXES
80         global configs
81         with open(filename) as f:
82                 for line in f:
83                         for regex in REGEXES:
84                                 p = re.compile(REGEXES[regex])
85                                 token = p.search(line)
86                                 if token is not None:
87                                         if regex == "TESTCASE":
88                                                 configs[regex] = re.search(REGEXES[regex], line).group(1)
89                                         else:
90                                                 configs[regex] = re.findall("\d+\.?\d*", line)[0]
91         row["SATTIME"] = configs["SATTIME"]
92         row["EXECTIME"] = configs["EXECTIME"]
93
94 def loadProblemName(row,filename):
95         with open(filename) as f:
96                 row["PROBLEM"] = f.readline().replace("\n","")
97 def loadTunerNumber(row, filename):
98         with open(filename) as f:
99                 row["TUNERNUMBER"] = f.readline().replace("\n","")
100 def analyzeLogs(file):
101         global configs
102         argprocess = AutoTunerArgParser()
103         printHeader(file)
104         rows = []
105         data = []
106         for i in range(argprocess.getRunNumber()):
107                 row = {"DECOMPOSEORDER" : "",
108                         "MUSTREACHGLOBAL" : "",
109                         "MUSTREACHLOCAL" : "",
110                         "MUSTREACHPRUNE" : "", 
111                         "OPTIMIZEORDERSTRUCTURE" : "",
112                         "ORDERINTEGERENCODING" : "",
113                         "PREPROCESS" : "",
114                         "NODEENCODING" : "",
115                         "EDGEENCODING" : "",
116                         "MUSTEDGEPRUNE" : "",
117                         "ELEMENTOPT" : "",
118                         "ENCODINGGRAPHOPT" : "", 
119                         "ELEMENTOPTSETS" : "", 
120                         "PROXYVARIABLE" : "", 
121                         "MUSTVALUE" : "", 
122                         "NAIVEENCODER" : "", 
123                         "VARIABLEORDER" : "",
124                         "PROBLEM":"",
125                         "SATTIME":"",
126                         "EXECTIME": "",
127                         "TUNERNUMBER":""
128                 }
129                 loadTunerNumber(row, argprocess.getFolder() + "/tunernum" + str(i))
130                 loadTunerInfo(row, argprocess.getFolder()+"/tuner"+str(i)+"used")
131                 loadSolverTime(row, argprocess.getFolder()+"/log"+str(i))
132                 loadProblemName(row, argprocess.getFolder()+"/problem"+str(i))
133                 data.append(dump(file, row))
134                 rows.append(row)
135         return rows, data
136
137 def tunerNumberAnalysis(file, rows):
138         global TUNABLEHEADER
139         tunercount = {}
140         tunernumber = {}
141         for row in rows:
142                 mystr=""
143                 for i in range(18):
144                         mystr+=row[TUNABLEHEADER[i]]
145                 if mystr not in tunercount:
146                         tunercount.update({mystr : 1})
147                         tunernumber.update({mystr : str(row["TUNERNUMBER"])})
148                 else :
149                         tunercount[mystr] += 1
150                         tunernumber[mystr] += "-" + str(row["TUNERNUMBER"])
151
152         problems = set(map(lambda x: x["PROBLEM"], rows))
153         print ("Number of repititive tuners")
154         for key in tunercount:
155                 if tunercount[key] > 1:
156                         print (key + "(ids:" + tunernumber[key]  + ") = #" + str(tunercount[key]))
157
158 def transformDataset(rows):
159         print(rows)
160 def main():
161         global TUNABLEHEADER
162         file = open("tuner.csv", "w")
163         rows, data = analyzeLogs(file)
164         tunerNumberAnalysis(file, rows)
165         file.close()
166         #transformDataset(data)
167         pl.plot(data, TUNABLEHEADER)
168         return
169
170 if __name__ == "__main__":
171         main()