Automating log reporter system
[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.args = self.parser.parse_args()
12
13         def getFolder(self):
14                 return self.args.folder[0]
15
16 PROBLEMS = []
17
18 TUNABLEHEADER = ["DECOMPOSEORDER", "MUSTREACHGLOBAL", "MUSTREACHLOCAL", "MUSTREACHPRUNE", "OPTIMIZEORDERSTRUCTURE",
19                 "ORDERINTEGERENCODING", "PREPROCESS", "NODEENCODING", "EDGEENCODING", "MUSTEDGEPRUNE", "ELEMENTOPT",
20                 "ENCODINGGRAPHOPT", "ELEMENTOPTSETS", "PROXYVARIABLE", "MUSTVALUE", "NAIVEENCODER", "VARIABLEORDER",
21                 "PROBLEM","SATTIME", "EXECTIME","TUNERNUMBER"]
22
23 configs = {"EXECTIME": "-",
24                 "SATTIME":"-",
25                 "TESTCASE":"-",
26                 "PREPROCESS" : "-",
27                 "ELEMENTOPT" : "-",
28                 "ELEMENTOPTSETS" : "-",
29                 "PROXYVARIABLE" : "-",
30                 "#SubGraph" : "-",
31                 "NODEENCODING" : "-",
32                 "EDGEENCODING" : "-",
33                 "NAIVEENCODER" :"-",
34                 "ENCODINGGRAPHOPT" : "-"
35                 }
36
37 REGEXES = {"EXECTIME": "CSOLVER solve time: (.*)",
38                 "SATTIME":"SAT Solving time: (.*)",
39                 "TESTCASE": "deserializing (.+) ...",
40                 "PREPROCESS" : "Param PREPROCESS = (.*)range=\[0,1\]",
41                 "ELEMENTOPT" : "Param ELEMENTOPT = (.*)range=\[0,1\]",
42                 "ELEMENTOPTSETS" : "Param ELEMENTOPTSETS = (.*)range=\[0,1\]",
43                 "PROXYVARIABLE" : "Param PROXYVARIABLE = (.*)range=\[1,5\]",
44                 "#SubGraph" : "#SubGraph = (.*)",
45                 "NODEENCODING" : "Param NODEENCODING = (.*)range=\[0,3\](.*)",
46                 "EDGEENCODING" : "Param EDGEENCODING = (.*)range=\[0,2\](.*)",
47                 "NAIVEENCODER" : "Param NAIVEENCODER = (.*)range=\[1,3\](.*)",
48                 "ENCODINGGRAPHOPT" : "Param ENCODINGGRAPHOPT = (.*)range=\[0,1\]"
49                 }
50
51 def printHeader(file):
52         global TUNABLEHEADER
53         mystr=""
54         for header in TUNABLEHEADER:
55                  mystr+=str(header)+","
56         file.write(mystr)
57         file.write("\n")
58
59 def dump(file, row):
60         global TUNABLEHEADER
61         mystr=""
62         data = []
63         for i in range(len(TUNABLEHEADER)):
64                 mystr += row[TUNABLEHEADER[i]]+ ","
65                 data.append(row[TUNABLEHEADER[i]])
66         print ("mystr is:"+ mystr)
67         file.write(mystr)
68         file.write("\n")
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 = list(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         global PROBLEMS
96         with open(filename) as f:
97                 problem = f.readline().replace("\n","")
98                 probNumber = int(f.readline())
99                 if probNumber >= len(PROBLEMS):
100                         PROBLEMS.insert(probNumber,problem)
101                 elif PROBLEMS[probNumber] != problem:
102                         PROBLEMS[probNumber] = problem
103                 row["PROBLEM"] = problem
104
105 def loadTunerNumber(row, filename):
106         with open(filename) as f:
107                 row["TUNERNUMBER"] = f.readline().replace("\n","")
108 def analyzeLogs(file):
109         global configs
110         argprocess = AutoTunerArgParser()
111         printHeader(file)
112         rows = []
113         data = []
114         i = 0
115         while True :
116                 row = {"DECOMPOSEORDER" : "",
117                         "MUSTREACHGLOBAL" : "",
118                         "MUSTREACHLOCAL" : "",
119                         "MUSTREACHPRUNE" : "", 
120                         "OPTIMIZEORDERSTRUCTURE" : "",
121                         "ORDERINTEGERENCODING" : "",
122                         "PREPROCESS" : "",
123                         "NODEENCODING" : "",
124                         "EDGEENCODING" : "",
125                         "MUSTEDGEPRUNE" : "",
126                         "ELEMENTOPT" : "",
127                         "ENCODINGGRAPHOPT" : "", 
128                         "ELEMENTOPTSETS" : "", 
129                         "PROXYVARIABLE" : "", 
130                         "MUSTVALUE" : "", 
131                         "NAIVEENCODER" : "", 
132                         "VARIABLEORDER" : "",
133                         "PROBLEM":"",
134                         "SATTIME":"",
135                         "EXECTIME": "",
136                         "TUNERNUMBER":""
137                 }
138                 try:
139                         loadTunerNumber(row, argprocess.getFolder() + "/tunernum" + str(i))
140                         loadTunerInfo(row, argprocess.getFolder()+"/tuner"+str(i)+"used")
141                         loadSolverTime(row, argprocess.getFolder()+"/log"+str(i))
142                         loadProblemName(row, argprocess.getFolder()+"/problem"+str(i))
143                         data.append(dump(file, row))
144                         rows.append(row)
145                 except IOError:
146                         break
147                 i += 1
148         return rows, data
149
150 def tunerCountAnalysis(file, rows):
151         global TUNABLEHEADER
152         global PROBLEMS
153         tunercount = {}
154         tunernumber = {}
155         for row in rows:
156                 mystr=""
157                 for i in range(18):
158                         if not row[TUNABLEHEADER[i]]:
159                                 mystr += "."
160                         else:
161                                 mystr+=row[TUNABLEHEADER[i]]
162                 if mystr not in tunercount:
163                         tunercount.update({mystr : 1})
164                         tunernumber.update({mystr : str(row["TUNERNUMBER"])})
165                 else :
166                         tunercount[mystr] += 1
167                         tunernumber[mystr] += "-" + str(row["TUNERNUMBER"])
168
169         problems = set(map(lambda x: x["PROBLEM"], rows))
170         print ("Number of repititive tuners")
171         for key in tunercount:
172                 if tunercount[key] > 1:
173                         print( key + "(ids:" + tunernumber[key]  + ") = #" + str(tunercount[key]) )
174
175 def combineRowForEachTuner(rows):
176         global PROBLEMS
177         newRows = []
178         combined = None
179         for row in rows:
180                 if row["PROBLEM"] == PROBLEMS[0]:
181                         combined = row
182                 for key in row:
183                         if row[key]:
184                                 combined[key] = row[key]
185                 if row["PROBLEM"] == PROBLEMS[len(PROBLEMS)-1]:
186                         newRows.append(combined)
187         return newRows
188
189 def transformDataset(rows):
190         print(rows)
191
192
193 def main():
194         global TUNABLEHEADER
195         file = open("tuner.csv", "w")
196         rows, data = analyzeLogs(file)
197         tunerCountAnalysis(file, combineRowForEachTuner(rows) )
198         file.close()
199         #transformDataset(data)
200         pl.plot(data, TUNABLEHEADER)
201
202
203 if __name__ == "__main__":
204         main()