コード例 #1
0
ファイル: Analyzer.py プロジェクト: gpilania/mooi
 def __init__(self, plotterTerminal="png"):
     self.plotter = ResultPlotter(plotterTerminal)
     self.metrics = MetricsCalc()
     
     self.pareto = None
     self.setResultDirectories([])
コード例 #2
0
ファイル: Analyzer.py プロジェクト: gpilania/mooi
class Analyzer:
    
    __PARETO__ = "pareto"
    __IMAGES_DIR__ = "images/"
    __COLORS__ = ["#dddddd", "#9400D3", "green", "blue", "red", "orange"]
    
    def __init__(self, plotterTerminal="png"):
        self.plotter = ResultPlotter(plotterTerminal)
        self.metrics = MetricsCalc()
        
        self.pareto = None
        self.setResultDirectories([])
        
    def setPareto(self, pareto):
        self.pareto = pareto
        self.addResultDirectory(pareto)
        
    def addResultDirectory(self, result):
        if result not in self.resultDirectories:
            self.nResults += 1
            self.resultDirectories.append(result)
            self.resultNames.append(self.getResultName(result))
            self._scanDirectory(result)
        
    def removeResultDirectory(self, result):
        if result in self.resultDirectories:
            self.resultDirectories.remove(result)
            self.setResultDirectories(self.resultDirectories)
        
    def setResultDirectories(self, results):
        self.resultDirectories = []
        self.resultNames = []
        self.functions = {}
        self.nResults = 0
        
        if self.pareto is not None:
            self.setPareto(self.pareto)
        for result in results:
            self.addResultDirectory(result)
        
    def getResultName(self, directory):
        directory = str(directory)
        if directory[-1] == "/":
            directory = directory[:-1]
        slash = max(directory.rfind("/"), directory.rfind("\\"))
        return directory[slash+1:]
    
    def getResultsForFunction(self, functionName):
        return self.functions[functionName.lower()]
    
    def getFunctionNames(self, includeNotSolved=False):
        return [function.functionName for function in self.functions.values() if includeNotSolved or \
                self._hasNonPareto(function.functionImplementation) or \
                self._hasNonPareto(function.variableImplementation)]
    
    def exportAllImages(self, directory, resultNames=None):
        if resultNames is None:
            resultNames = self.resultNames
        for functionName in self.getFunctionNames():
            function = self.functions[functionName.lower()]
            filename = directory + "/" + function.functionName
            generation = [0] * len(resultNames)
            self.exportToImage(function, generation, True, resultNames, filename + "_fun.png")
            self.exportToImage(function, generation, False, resultNames, filename + "_var.png")
    
    def exportToImage(self, function, generation, functionSpace, resultNames, filename, latex=False, window=None):
        toPlot = self._getSolutionsToPlot(function, generation, functionSpace, resultNames)
        if functionSpace:
            if latex:
                axis = ["$f_1$", "$f_2$", "$f_3$"]
            else:
                axis = ["F1", "F2", "F3"]
        else:
            if latex:
                axis = ["$x_1$", "$x_2$", "$x_3$"]
            else:
                axis = ["x1", "x2", "x3"]
                
        functionName = Utils.getFunctionNameLatex(function.functionName) if latex else function.functionName
        if latex:
            for solution in toPlot:
                solution[0] = Utils.getResultNameLatex(solution[0])
        self.plotter.plotSolution(toPlot, functionName, None if functionSpace else "Parameter space", \
                                  axis[0], axis[1], axis[2], window, filename)
      
    def _getSolutionsToPlot(self, problem, generation, functionSpace, resultNames):
        solutions = []
        if Analyzer.__PARETO__ in resultNames:
            resultNames.remove(Analyzer.__PARETO__)
            resultNames.insert(0, Analyzer.__PARETO__)
            
        k = 0
        for name in resultNames:
            k += 1
            if functionSpace:
                solution = problem.getFunctionSolution(name)
            else:
                solution = problem.getVariableSolution(name)
            if solution is not None:
                colorIdx = 0
                if name != Analyzer.__PARETO__:
                    colorIdx = self.resultNames.index(name) + 1
                rgb = Analyzer.__COLORS__[colorIdx]
#                rgb = 3*[0]
#                for p in xrange(3):
#                    if k & (1 << p) > 0:
#                        rgb[p] = 255
                points = solution.getSolutionPoints(generation[k-1])
                solutions.append([name, points, rgb])
            
        return solutions
            
    def _hasNonPareto(self, implementations):
        if len(implementations) > 1:
            return True
        if len(implementations) == 0:
            return False
        return Analyzer.__PARETO__ not in implementations.keys()
    
    def _scanDirectory(self, directory):
        if not os.path.exists(directory) or not os.path.isdir(directory):
            print >> sys.stderr, "Directory '%s' does not exist!" % directory
            return
        
        resultName = self.getResultName(directory)
        for filename in dircache.listdir(directory):
            filename = str(directory + "/" + filename)
#            fileType, _ = mimetypes.guess_type(filename)
            #if fileType is None or "text" not in fileType or not self.isSolutionFile(filename):
            if not Utils.isSolutionFile(filename):
                continue
            
            functionName = Utils.getFunctionName(filename)
            genPos = max(-1, functionName.rfind("."), functionName.rfind("-"), functionName.rfind("_"))
            generation = 1 << 30
            if genPos >= 0:
                try:
                    generation = int(functionName[genPos+1:])
                    functionName = functionName[:genPos]
                except:
                    pass
                
            fnId = functionName.lower()
            if fnId in self.functions:
                function = self.functions[fnId]
            else:
                function = MOSolution(functionName)
                self.functions[fnId] = function
                
            if Utils.isFunctionFile(filename):
                function.addFunctionSolution(resultName, filename, generation)
            else:
                function.addVariableSolution(resultName, filename, generation)
            
    def getFunctionResults(self, functionName, resultNames):
        function = self.getResultsForFunction(functionName)
        solutions = []
        for name in resultNames:
            if name.lower() != Analyzer.__PARETO__:
                result = function.getFunctionSolution(name)
                if result is not None:
                    solutions.append([name, [result.getSolutionPoints(idx) for idx in xrange(result.count())]])
                
        return solutions
    
    def getFunctionPareto(self, functionName):
        pareto = self.getResultsForFunction(functionName).getFunctionSolution(Analyzer.__PARETO__)
        if pareto is None:
            return None
        return pareto.getSolutionPoints(0)
    
    def getFormattedValue(self, data1, data2, best, decimalFormat="%.4f", bestFormat="\\textbf{%s}"):
        if data1 is None:
            return "---"
        
        if isinstance(data1, types.StringType):
            return data1
        
        value = decimalFormat % data1
        if data2 is not None:
            value += " / " + (decimalFormat % data2)
        if best:
            value = bestFormat % value
        return value
    
    def getCurrentBestResult(self):
        convIdx = len(self.metrics.labels) - 2
        distIdx = convIdx + 1
        convergence = self.metrics.metricMean[convIdx]
        distribution = self.metrics.metricMean[distIdx]
        best = 0
        for i in xrange(1, self.nResults - 1):
            if convergence[i] > convergence[best] + Utils.__EPS__:
                best = i
            elif abs(convergence[i] - convergence[best]) < Utils.__EPS__ and distribution[i] > distribution[best]:
                best = i
                
        return best
    
    def generateMetricImage(self, functionName, metricName, metricIdx, filename, latex=False):
        print "    Generating figure for metric %s in problem %s" % (metricName, functionName)
        results = []
        for i in xrange(self.nResults - 1):
            name = Utils.getResultNameLatex(self.resultNames[i]) if latex else self.resultNames[i]
            result = [name, [self.metrics.metricMin[metricIdx][i], self.metrics.metricQ1[metricIdx][i], self.metrics.metricMean[metricIdx][i], \
                                       self.metrics.metricQ3[metricIdx][i], self.metrics.metricMax[metricIdx][i]], Analyzer.__COLORS__[i+1]]
            results.append(result)
            
        fname = Utils.getFunctionNameLatex(functionName) if latex else functionName
        mname = Utils.getMetricNameLatex(metricName) if latex else metricName
        self.plotter.plotIndicators(results, fname, "", "", mname, filename)
    
    def _getRun(self, functionName, resultName, rank=0.0):
        results = self.getFunctionResults(functionName, [resultName])
        runs = []

        pareto = self.getFunctionPareto(functionName)
        metrics = Metrics(pareto, [results[0][1]])
        for run in xrange(len(results[0][1])):
            metrics.setSolutionsToCompare(0, run, None, None)
            value = metrics.deltaP()
            runs.append([value, run])
        runs.sort(key = lambda x : x[0])
        idx = max(0, int(round(len(runs) * rank)) - 1)
        return runs[idx][1]
    
    def generateImages(self, functionName, results, filenames, rank=0.0, latex=False):
        function = self.functions[functionName.lower()]
        
        window = [[1<<30, -(1<<30)] for _ in xrange(self.metrics.dim)]
        bestRun = [0] * len(results)
        for point in self.getFunctionPareto(functionName):
            for d in xrange(self.metrics.dim):
                window[d][0] = min(window[d][0], point[d])
                window[d][1] = max(window[d][1], point[d])
        for i in xrange(len(results)):
            resultName = results[i]
            bestRun[i] = self._getRun(functionName, resultName, rank)
            run = self.getFunctionResults(functionName, [resultName])[0][1][bestRun[i]]
            for point in run:
                for d in xrange(self.metrics.dim):
                    #window[d] = max(window[d], math.ceil(point[d] * 10) / 10.0)
                    window[d][0] = min(window[d][0], point[d])
                    window[d][1] = max(window[d][1], point[d])
            
        for i in xrange(len(results)):
            resultName = results[i]
            print "    Generating figure of %s for %s" % (resultName, functionName)
            resultNames = [Analyzer.__PARETO__, resultName]
            generation = [0, bestRun[i]]
            
            self.exportToImage(function, generation, True, resultNames, filenames[i], latex, window)
        
    def computeMetrics(self, functionName):
        pareto = self.getFunctionPareto(functionName)
        results = self.getFunctionResults(functionName, self.resultNames)
        self.metrics.computeMetrics(pareto, results, functionName)