d47df1f41c2e5eb88d2e09cb13c725324c4760f1
[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 PROBLEMS = []
21
22 TUNABLEHEADER = ["DECOMPOSEORDER", "MUSTREACHGLOBAL", "MUSTREACHLOCAL", "MUSTREACHPRUNE", "OPTIMIZEORDERSTRUCTURE",
23                 "ORDERINTEGERENCODING", "PREPROCESS", "NODEENCODING", "EDGEENCODING", "MUSTEDGEPRUNE", "ELEMENTOPT",
24                 "ENCODINGGRAPHOPT", "ELEMENTOPTSETS", "PROXYVARIABLE", "MUSTVALUE", "NAIVEENCODER", "VARIABLEORDER",
25                 "PROBLEM","SATTIME", "EXECTIME","TUNERNUMBER"]
26
27 configs = {"EXECTIME": "-",
28                 "SATTIME":"-",
29                 "TESTCASE":"-",
30                 "PREPROCESS" : "-",
31                 "ELEMENTOPT" : "-",
32                 "ELEMENTOPTSETS" : "-",
33                 "PROXYVARIABLE" : "-",
34                 "#SubGraph" : "-",
35                 "NODEENCODING" : "-",
36                 "EDGEENCODING" : "-",
37                 "NAIVEENCODER" :"-",
38                 "ENCODINGGRAPHOPT" : "-"
39                 }
40
41 REGEXES = {"EXECTIME": "CSOLVER solve time: (.*)",
42                 "SATTIME":"SAT Solving time: (.*)",
43                 "TESTCASE": "deserializing (.+) ...",
44                 "PREPROCESS" : "Param PREPROCESS = (.*)range=\[0,1\]",
45                 "ELEMENTOPT" : "Param ELEMENTOPT = (.*)range=\[0,1\]",
46                 "ELEMENTOPTSETS" : "Param ELEMENTOPTSETS = (.*)range=\[0,1\]",
47                 "PROXYVARIABLE" : "Param PROXYVARIABLE = (.*)range=\[1,5\]",
48                 "#SubGraph" : "#SubGraph = (.*)",
49                 "NODEENCODING" : "Param NODEENCODING = (.*)range=\[0,3\](.*)",
50                 "EDGEENCODING" : "Param EDGEENCODING = (.*)range=\[0,2\](.*)",
51                 "NAIVEENCODER" : "Param NAIVEENCODER = (.*)range=\[1,3\](.*)",
52                 "ENCODINGGRAPHOPT" : "Param ENCODINGGRAPHOPT = (.*)range=\[0,1\]"
53                 }
54
55 def printHeader(file):
56         global TUNABLEHEADER
57         mystr=""
58         for header in TUNABLEHEADER:
59                  mystr+=str(header)+","
60         print >>file, mystr
61
62 def dump(file, row):
63         global TUNABLEHEADER
64         mystr=""
65         data = []
66         for i in range(len(TUNABLEHEADER)):
67                 mystr += row[TUNABLEHEADER[i]]+ ","
68                 data.append(row[TUNABLEHEADER[i]])
69         print ("mystr is:"+ mystr)
70         print >>file, mystr
71         return data
72
73 def loadTunerInfo(row, filename):
74         with open(filename) as f:
75                 for line in f:
76                         numbers = re.findall('\d+',line)
77                         numbers = map(int,numbers)
78                         row[TUNABLEHEADER[numbers[3]]] = row[TUNABLEHEADER[numbers[3]]] + str(numbers[7])
79
80 def loadSolverTime(row, filename):
81         global REGEXES
82         global configs
83         with open(filename) as f:
84                 for line in f:
85                         for regex in REGEXES:
86                                 p = re.compile(REGEXES[regex])
87                                 token = p.search(line)
88                                 if token is not None:
89                                         if regex == "TESTCASE":
90                                                 configs[regex] = re.search(REGEXES[regex], line).group(1)
91                                         else:
92                                                 configs[regex] = re.findall("\d+\.?\d*", line)[0]
93         row["SATTIME"] = configs["SATTIME"]
94         row["EXECTIME"] = configs["EXECTIME"]
95
96 def loadProblemName(row,filename):
97         global PROBLEMS
98         with open(filename) as f:
99                 problem = f.readline().replace("\n","")
100                 probNumber = int(f.readline())
101                 if probNumber >= len(PROBLEMS):
102                         PROBLEMS.insert(probNumber,problem)
103                 elif PROBLEMS[probNumber] != problem:
104                         PROBLEMS[probNumber] = problem
105                 row["PROBLEM"] = problem
106
107 def loadTunerNumber(row, filename):
108         with open(filename) as f:
109                 row["TUNERNUMBER"] = f.readline().replace("\n","")
110 def analyzeLogs(file):
111         global configs
112         argprocess = AutoTunerArgParser()
113         printHeader(file)
114         rows = []
115         data = []
116         for i in range(argprocess.getRunNumber()):
117                 row = {"DECOMPOSEORDER" : "",
118                         "MUSTREACHGLOBAL" : "",
119                         "MUSTREACHLOCAL" : "",
120                         "MUSTREACHPRUNE" : "", 
121                         "OPTIMIZEORDERSTRUCTURE" : "",
122                         "ORDERINTEGERENCODING" : "",
123                         "PREPROCESS" : "",
124                         "NODEENCODING" : "",
125                         "EDGEENCODING" : "",
126                         "MUSTEDGEPRUNE" : "",
127                         "ELEMENTOPT" : "",
128                         "ENCODINGGRAPHOPT" : "", 
129                         "ELEMENTOPTSETS" : "", 
130                         "PROXYVARIABLE" : "", 
131                         "MUSTVALUE" : "", 
132                         "NAIVEENCODER" : "", 
133                         "VARIABLEORDER" : "",
134                         "PROBLEM":"",
135                         "SATTIME":"",
136                         "EXECTIME": "",
137                         "TUNERNUMBER":""
138                 }
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         return rows, data
146
147 def tunerCountAnalysis(file, rows):
148         global TUNABLEHEADER
149         global PROBLEMS
150         tunercount = {}
151         tunernumber = {}
152         for row in rows:
153                 mystr=""
154                 for i in range(18):
155                         if not row[TUNABLEHEADER[i]]:
156                                 mystr += "."
157                         else:
158                                 mystr+=row[TUNABLEHEADER[i]]
159                 if mystr not in tunercount:
160                         tunercount.update({mystr : 1})
161                         tunernumber.update({mystr : str(row["TUNERNUMBER"])})
162                 else :
163                         tunercount[mystr] += 1
164                         tunernumber[mystr] += "-" + str(row["TUNERNUMBER"])
165
166         problems = set(map(lambda x: x["PROBLEM"], rows))
167         print ("Number of repititive tuners")
168         for key in tunercount:
169                 if tunercount[key] > 1:
170                         print key + "(ids:" + tunernumber[key]  + ") = #" + str(tunercount[key])
171
172 def combineRowForEachTuner(rows):
173         global PROBLEMS
174         newRows = []
175         combined = None
176         for row in rows:
177                 if row["PROBLEM"] == PROBLEMS[0]:
178                         combined = row
179                 for key in row:
180                         if row[key]:
181                                 combined[key] = row[key]
182                 if row["PROBLEM"] == PROBLEMS[len(PROBLEMS)-1]:
183                         newRows.append(combined)
184         return newRows
185
186 def transformDataset(rows):
187         print(rows)
188
189
190 def main():
191         global TUNABLEHEADER
192         file = open("tuner.csv", "w")
193         rows, data = analyzeLogs(file)
194         tunerCountAnalysis(file, combineRowForEachTuner(rows) )
195         file.close()
196         #transformDataset(data)
197         pl.plot(data, TUNABLEHEADER)
198
199
200 if __name__ == "__main__":
201         main()