def readMeasuredValueFromFile(location): """Reads the measured value of a path from a file. Arguments: location: Location of the file. Returns: Measured value of a path, represented as a number (either an integer or a floating-point number). """ try: measuredValueFileHandler = open(location, "r") except EnvironmentError as e: errMsg = ("Error reading the measured value of a path from " "the file located at %s: %s" % (location, e)) raise GameTimeError(errMsg) else: with measuredValueFileHandler: line = measuredValueFileHandler.readline().strip() try: result = int(line) except ValueError: try: result = float(line) except ValueError: errMsg = ("The following line, in the file located " "at %s, does not represent a valid " "measured value of a path: %s" % (location, line)) raise GameTimeError(errMsg) return result
def setSmtSolverAndModelParser(self, smtSolverName): """ Sets the SMT solver and model parser objects associated with this :class:`~gametime.projectConfiguration.ProjectConfiguration` object to ones that can interface with the SMT solver whose name is provided. Arguments: smtSolverName: Name of an SMT solver. """ smtSolverName = smtSolverName.lower() if smtSolverName.startswith("boolector"): if config.SOLVER_BOOLECTOR == "": errMsg = ("The Boolector executable was not found " "during the configuration of GameTime. " "This GameTime project cannot use Boolector " "as its backend SMT solver.") raise GameTimeError(errMsg) else: from smt.solvers.boolectorSolver import BoolectorSolver from smt.solvers.boolectorSolver import SatSolver satSolverName = smtSolverName[len("boolector"):] satSolverName = satSolverName.split("-")[-1] boolectorSatSolver = \ SatSolver.getSatSolver(satSolverName) self.smtSolver = BoolectorSolver(boolectorSatSolver) from smt.parsers.boolectorModelParser \ import BoolectorModelParser self.smtModelParser = BoolectorModelParser() elif smtSolverName == "z3": if config.SOLVER_Z3 == "": errMsg = ("The Z3 Python frontend was not found " "during the configuration of GameTime. " "This GameTime project cannot use Z3 " "as its backend SMT solver.") raise GameTimeError(errMsg) else: from smt.solvers.z3Solver import Z3Solver self.smtSolver = Z3Solver() from smt.parsers.z3ModelParser import Z3ModelParser self.smtModelParser = Z3ModelParser() elif smtSolverName == "": errMsg = "SMT solver not specified." raise GameTimeError(errMsg) else: errMsg = ("Incorrect option specified for " "the SMT solver: %s") % smtSolverName raise GameTimeError(errMsg)
def numPaths(dag, source, sink): """ Arguments: dag: DAG represented by a :class:`~gametime.nxHelper.Dag` object. source: Source node. sink: Sink node. Returns: Number of paths in the DAG provided. """ # Dictionary that maps each node to the number of paths in the # DAG provided from the input source node to that node. nodesToNumPaths = {} nodesToNumPaths[source] = 1 # Topologically sort the nodes in the graph. nodesToVisit = nx.topological_sort(dag) if nodesToVisit.pop(0) != source: errMsg = ("The source node should be the first node in " "a topological sort of the control-flow graph.") raise GameTimeError(errMsg) while len(nodesToVisit) > 0: currNode = nodesToVisit.pop(0) numPathsToNode = 0 for inEdge in dag.in_edges(currNode): inNeighbor = inEdge[0] numPathsToNode += nodesToNumPaths[inNeighbor] nodesToNumPaths[currNode] = numPathsToNode return nodesToNumPaths[sink]
def _generateOtherSourcesFile(projectConfig): """Creates a file that contains the paths of other files to be merged with the source file. Arguments: projectConfig: :class:`~gametime.projectConfiguration.ProjectConfiguration` object that represents the configuration of a GameTime project. Returns: Path to the file that contains the paths of other files to be merged with the source file. """ otherSourcesFilePath = os.path.join(projectConfig.locationTempDir, config.TEMP_MERGED) # Create the file. try: otherSourcesFileHandler = open(otherSourcesFilePath, "w") except EnvironmentError as e: errMsg = ("Error creating a temporary file located at %s, " "which stores the paths of the other files to be " "merged with the source file: %s" % (otherSourcesFilePath, e)) raise GameTimeError(errMsg) else: with otherSourcesFileHandler: for filePath in projectConfig.merged: otherSourcesFileHandler.write("%s\n" % filePath) return otherSourcesFilePath
def readAssignmentsFromFile(location): """ Reads, from a file, the assignments to variables that would drive an execution of the code under analysis along a path. Arguments: location: Location of the file. Returns: Dictionary of assignments to variables that would drive an execution of the code under analysis along a path. """ try: assignmentFileHandler = open(location, "r") except EnvironmentError as e: errMsg = ("Error reading the assignments to variables " "that would drive an execution of the code " "along a path: %s") % e raise GameTimeError(errMsg) else: assignments = {} with assignmentFileHandler: assignmentFileLines = assignmentFileHandler.readlines() for line in assignmentFileLines: (variable, assignment) = \ line.strip().replace(";", "").split(" = ") assignments[variable] = assignment return assignments
def readArrayAccessesFromFile(location): """ Reads information about the array accesses made in conditions along a path from a file. Arguments: location: Location of the file. Returns: Dictionary that maps an array name to a list of tuples, each of which contains the numbers of the temporary index variables in an array access. """ try: arrayAccessesFileHandler = open(location, "r") except EnvironmentError as e: errMsg = ("Error reading information about the array accesses " "made in conditions along a path: %s") % e raise GameTimeError(errMsg) else: arrayAccesses = {} with arrayAccessesFileHandler: arrayAccessLines = arrayAccessesFileHandler.readlines() for arrayAccessLine in arrayAccessLines: # Process the array access information. arrayAccessLine = arrayAccessLine.strip().split(": ") arrayName = arrayAccessLine[0] tempIndicesTuples = literal_eval(arrayAccessLine[1]) if arrayName in arrayAccesses: arrayAccesses[arrayName].extend(tempIndicesTuples) else: arrayAccesses[arrayName] = tempIndicesTuples return arrayAccesses
def readConditionTruthsFromFile(location): """ Reads the line numbers of the conditional points in the code being analyzed, along with their truth values along a path, from a file. Arguments: location: Location of the file. Returns: Dictionary that associates the line numbers of the conditional points in the code being analyzed with their truth values. """ try: conditionTruthsFileHandler = open(location, "r") except EnvironmentError as e: errMsg = ("Error reading line numbers of the conditional " "points in the code being analyzed, along with " "their truth values along a path: %s") % e raise GameTimeError(errMsg) else: conditionTruths = {} with conditionTruthsFileHandler: conditionTruthsFileLines = \ conditionTruthsFileHandler.readlines() for line in conditionTruthsFileLines: (lineNumber, conditionTruth) = line.strip().split(": ") conditionTruths[lineNumber] = conditionTruth == "True" return conditionTruths
def readConditionEdgesFromFile(location): """ Reads the numbers of the conditions along a path, and the edges that are associated with the conditions, from a file. Arguments: location: Location of the file. Returns: Dictionary that associates the number of a condition with the edge in the directed acyclic graph that is associated with the condition. The edge is represented as a tuple. """ try: conditionEdgesFileHandler = open(location, "r") except EnvironmentError as e: errMsg = ("Error reading the numbers of the conditions along " "a path, and the edges that are associated with " "the conditions: %s") % e raise GameTimeError(errMsg) else: conditionEdges = {} with conditionEdgesFileHandler: conditionEdgesFileLines = conditionEdgesFileHandler.readlines() for line in conditionEdgesFileLines: (conditionNum, edge) = line.strip().split(": ") edge = tuple(edge.strip().split(" ")) conditionEdges[int(conditionNum.strip())] = edge return conditionEdges
def writeDagToDotFile(dag, location, dagName="", edgesToLabels=None, highlightedEdges=None, highlightColor="red"): """Writes the directed acyclic graph provided to a file in DOT format. Arguments: location: Location of the file. dagName: Name of the directed acyclic graph, as will be written to the file. If this argument is not provided, the directed acyclic graph will not have a name. edgesToLabels: Dictionary that maps an edge to the label that will annotate the edge when the DOT file is processed by a visualization tool. If this argument is not provided, these annotations will not be made. highlightedEdges: List of edges that will be highlighted when the DOT file is processed by a visualization tool. If this argument is not provided, no edges will be highlighted. highlightColor: Color of the highlighted edges. This argument can be any value that is legal in the DOT format. If the `highlightedEdges` argument is not provided, this argument is ignored. """ _, extension = os.path.splitext(location) if extension.lower() != ".dot": location = "%s.dot" % location dagName = " %s" % dagName.strip() contents = [] contents.append("digraph%s {" % dagName) for edge in dag.edges(): line = " %s -> %s" % edge attributes = [] if edgesToLabels: attributes.append("label = \"%s\"" % edgesToLabels[edge]) if highlightedEdges and edge in highlightedEdges: attributes.append("color = \"%s\"" % highlightColor) if len(attributes) > 0: line += " [%s]" % ", ".join(attributes) contents.append("%s;" % line) contents.append("}") try: dagDotFileHandler = open(location, "w") except EnvironmentError as e: errMsg = ("Error writing the DAG to a file located at %s: %s" % (location, e)) raise GameTimeError(errMsg) else: with dagDotFileHandler: dagDotFileHandler.write("\n".join(contents))
def setIlpSolver(self, ilpSolverName): """ Sets the PuLP solver object associated with this :class:`~gametime.projectConfiguration.ProjectConfiguration` object to one that can interface with the integer linear programming solver whose name is provided. Arguments: ilpSolverName: Name of an integer linear programming solver. """ def _ilpSolverErrMsg(ilpSolverName): """ Arguments: ilpSolverName: Name of an integer linear programming solver. Returns: Error message that informs the user that the integer linear programming solver, whose name is provided, cannot be used for this GameTime project. """ if ilpSolverName == "": return ("The default integer linear programming solver " "of the PuLP package was not found. " "This GameTime project cannot use it as its " "backend integer linear programming solver.") ilpSolverName = pulpHelper.getProperName(ilpSolverName) return ("The integer linear programming solver %s " "was not found. This GameTime project cannot use %s " "as its backend integer linear programming solver." % (ilpSolverName, ilpSolverName)) ilpSolverName = ilpSolverName.lower() if not pulpHelper.isIlpSolverName(ilpSolverName): errMsg = ("Incorrect option specified for the integer " "linear programming solver: %s") % ilpSolverName raise GameTimeError(errMsg) else: ilpSolver = pulpHelper.getIlpSolver(ilpSolverName, self) if ilpSolver is not None: self.ilpSolver = ilpSolver else: raise GameTimeError(_ilpSolverErrMsg(ilpSolverName))
def writeIlpProblemToLpFile(self, location): """ Writes, to an LP file, the integer linear programming problem that, when solved, produced this path. Arguments: location: Location of the file. """ if self.ilpProblem is not None: _, extension = os.path.splitext(location) if extension.lower() != ".lp": location = location + ".lp" try: self.ilpProblem.writeLP(location) except (PulpError, EnvironmentError) as e: errMsg = ("Error writing the integer linear programming " "problem to an LP file: %s") % e raise GameTimeError(errMsg) else: errMsg = ("This path is not associated with an integer linear " "programming problem.") raise GameTimeError(errMsg)
def removeFile(location): """Removes the file at the provided location. This is a wrapper around the :func:`~os.remove` function of the :mod:`os` module, but does not raise an exception if the file is not present. Arguments: location: Location of the file to be removed. """ try: if os.path.exists(location): os.remove(location) except EnvironmentError as e: raise GameTimeError("Cannot remove file located at %s: %s" % (location, e))
def writeMeasuredValueToFile(self, location): """Writes the measured value of this path to a file. Arguments: location: Location of the file. """ try: measuredValueFileHandler = open(location, "w") except EnvironmentError as e: errMsg = ("Error writing the measured value of the path " "to the file located at %s: %s" % (location, e)) raise GameTimeError(errMsg) else: with measuredValueFileHandler: measuredValueFileHandler.write(self.getMeasuredValue())
def writeConditionsToFile(self, location): """ Writes the conditions along this path to a file. Arguments: location: Location of the file. """ try: conditionsFileHandler = open(location, "w") except EnvironmentError as e: errMsg = "Error writing conditions along the path: %s" % e raise GameTimeError(errMsg) else: with conditionsFileHandler: conditionsFileHandler.write(self.getConditions())
def writeArrayAccessesToFile(self, location): """ Writes information about the array accesses made in conditions along this path to a file. Arguments: location: Location of the file. """ try: arrayAccessesFileHandler = open(location, "w") except EnvironmentError as e: errMsg = ("Error writing information about the array accesses " "made in conditions along the path: %s") % e raise GameTimeError(errMsg) else: with arrayAccessesFileHandler: arrayAccessesFileHandler.write(self.getArrayAccesses())
def writeLineNumbersToFile(self, location): """ Writes the line numbers of the source-level statements that lie along this path to a file. Arguments: location: Location of the file. """ try: lineNumbersFileHandler = open(location, "w") except EnvironmentError as e: errMsg = ("Error writing line numbers of the source-level " "statements along the path: %s") % e raise GameTimeError(errMsg) else: with lineNumbersFileHandler: lineNumbersFileHandler.write(self.getLineNumbers())
def writeNodesToFile(self, location): """ Writes the IDs of the nodes in a directed acyclic graph along this path to a file. Arguments: location: Location of the file. """ try: nodesFileHandler = open(location, "w") except EnvironmentError as e: errMsg = ("Error writing the IDs of the nodes in " "a directed acyclic graph along the path: %s") % e raise GameTimeError(errMsg) else: with nodesFileHandler: nodesFileHandler.write(self.getNodes())
def createDir(location): """Creates the leaf directory in the path specified, along with any intermediate-level directories needed to contain the directory. This is a wrapper around the :func:`~os.makedirs` function of the :mod:`os` module, but does not raise an exception if the directory is already present, Arguments: location: Location of the directory to be created. """ try: if not os.path.isdir(location): os.makedirs(location) except EnvironmentError as e: if e.errno != errno.EEXIST: raise GameTimeError("Cannot create directory located at %s: %s" % (location, e))
def writeConditionTruthsToFile(self, location): """ Writes the line numbers of the conditional points in the code being analyzed, along with their truth values, to a file. Arguments: location: Location of the file. """ try: conditionTruthsFileHandler = open(location, "w") except EnvironmentError as e: errMsg = ("Error writing line numbers of the conditional " "points in the code being analyzed, along with " "their truth values: %s") % e raise GameTimeError(errMsg) else: with conditionTruthsFileHandler: conditionTruthsFileHandler.write(self.getConditionTruths())
def writeConditionEdgesToFile(self, location): """ Writes the numbers of the conditions along this path, and the edges that are associated with the conditions, to a file. Arguments: location: Location of the file. """ try: conditionEdgesFileHandler = open(location, "w") except EnvironmentError as e: errMsg = ("Error writing the numbers of the conditions along " "the path, and the edges that are associated with " "the conditions: %s") % e raise GameTimeError(errMsg) else: with conditionEdgesFileHandler: conditionEdgesFileHandler.write(self.getConditionEdges())
def writeAssignmentsToFile(self, location): """ Writes the assignments to variables that would drive an execution of the code under analysis along this path to a file. Arguments: location: Location of the file. """ try: assignmentFileHandler = open(location, "w") except EnvironmentError as e: errMsg = ("Error writing the assignments to variables " "that would drive an execution of the code " "along the path: %s") % e raise GameTimeError(errMsg) else: with assignmentFileHandler: assignmentFileHandler.write(self.getAssignments())
def constructDag(location): """Constructs a :class:`~gametime.nxHelper.Dag` object to represent the directed acyclic graph described in DOT format in the file provided. Arguments: location: Path to the file describing a directed acyclic graph in DOT format. Returns: :class:`~gametime.nxHelper.Dag` object that represents the directed acyclic graph. """ try: dagDotFileHandler = open(location, "r") except EnvironmentError as e: errMsg = ("Error opening the DOT file, located at %s, that contains " "the directed acyclic graph to analyze: %s") % (location, e) raise GameTimeError(errMsg) else: with dagDotFileHandler: dagDotFileLines = dagDotFileHandler.readlines() # This is a hacky way of parsing the file, but for this # small and constant a use case, we should be fine: we should not # have to generate a parser from a grammar. If, however, for some # reason, the format with which the Phoenix and Python code communicate # changes, this should be modified or made more robust. dagDotFileLines = dagDotFileLines[1:-1] dagDotFileLines = [line.replace(lsep, "") for line in dagDotFileLines] dagDotFileLines = [line.replace(";", "") for line in dagDotFileLines] dagDotFileLines = [line.replace("->", "") for line in dagDotFileLines] dagDotFileLines = [line.strip() for line in dagDotFileLines] # Construct the graph. dag = Dag() for line in dagDotFileLines: edge = line.split(" ") edge = [node for node in edge if node != ""] dag.add_edge(edge[0], edge[1]) dag.loadVariables() return dag
def writeAggIndexExprsToFile(self, location): """ Writes information about the expressions associated with the temporary index variables of aggregate accesses along this path to a file. Arguments: location: Location of the file. """ try: aggIndexExprsFileHandler = open(location, "w") except EnvironmentError as e: errMsg = ("Error writing information about the expressions " "associated with the temporary index variables of " "aggregate accesses along this path: %s") % e raise GameTimeError(errMsg) else: with aggIndexExprsFileHandler: aggIndexExprsFileHandler.write(self.getAggIndexExprs())
def readAggIndexExprsFromFile(location): """ Reads, from a file, information about the expressions associated with the temporary index variables of aggregate accesses along a path. Arguments: location: Location of the file. Returns: Dictionary that maps the number of a temporary index variable to an ``IndexExpression`` object. """ try: aggIndexExprsFileHandler = open(location, "r") except EnvironmentError as e: errMsg = ("Error reading information about the expressions " "associated with the temporary index variables of " "aggregate accesses along a path: %s") % e raise GameTimeError(errMsg) else: aggIndexExprs = {} with aggIndexExprsFileHandler: aggIndexExprsLines = aggIndexExprsFileHandler.readlines() for aggIndexExprsLine in aggIndexExprsLines: lineTokens = aggIndexExprsLine.strip().split(": ") tempIndexNumber = int(lineTokens[0]) lineTokens = lineTokens[1].split() if len(lineTokens) == 1: varName = lineTokens[0] aggIndexExprs[tempIndexNumber] = \ VariableIndexExpression(varName) else: arrayVarName = lineTokens[0] indices = tuple(int(index) for index in lineTokens[1:]) aggIndexExprs[tempIndexNumber] = \ ArrayIndexExpression(arrayVarName, indices) return aggIndexExprs
def writeHistogramToFile(location, paths, bins=10, range=None, measured=False): """Computes a histogram from the values of a list of feasible paths generated by GameTime, and writes the histogram to a file. Each line of the file has the left edge of each bin and the number of samples in each bin, with both of the values separated by whitespace. Arguments: location: Location of the file. paths: List of feasible paths generated by GameTime, each represented by a :class:`~gametime.path.Path` object. bins: Same purpose as the same-named argument of the function :func:`numpy.histogram`. range: Same purpose as the same-named argument of the function :func:`numpy.histogram`. measured: `True` if, and only if, the values that will be used for the histogram are the measured values of the feasible paths. """ logger.info("Creating histogram...") hist, binEdges = computeHistogram(paths, bins, range, measured) try: histogramFileHandler = open(location, "w") except EnvironmentError as e: errMsg = ("Error writing the histogram to the file located " "at %s: %s" % (location, e)) raise GameTimeError(errMsg) else: with histogramFileHandler: for binEdge, sample in zip(binEdges, hist): histogramFileHandler.write("%s\t%s\n" % (binEdge, sample)) logger.info("Histogram created.")
def readNodesFromFile(location): """ Reads the IDs of the nodes in a directed acyclic graph along a path from a file. Arguments: location: Location of the file. Returns: IDs of the nodes in a directed acyclic graph along a path, represented as a list of strings. """ try: nodesFileHandler = open(location, "r") except EnvironmentError as e: errMsg = ("Error reading the IDs of the nodes in " "a directed acyclic graph along a path: %s") % e raise GameTimeError(errMsg) else: with nodesFileHandler: nodes = nodesFileHandler.readline().strip().split() return nodes
def readConditionsFromFile(location): """ Reads the conditions along a path from a file. Arguments: location: Location of the file. Returns: Conditions along a path, represented as a list of strings. """ try: conditionsFileHandler = open(location, "r") except EnvironmentError as e: errMsg = "Error reading conditions along a path: %s" % e raise GameTimeError(errMsg) else: with conditionsFileHandler: conditions = conditionsFileHandler.readlines() conditions = [condition.strip() for condition in conditions] conditions = [condition for condition in conditions if condition is not ""] return conditions
def readLineNumbersFromFile(location): """ Reads the line numbers of the source-level statements that lie along a path from a file. Arguments: location: Location of the file. Returns: Line numbers of the source-level statements along this path, represented as a list of positive integers. """ try: lineNumbersFileHandler = open(location, "r") except EnvironmentError as e: errMsg = ("Error reading line numbers of the source-level " "statements along a path: %s") % e raise GameTimeError(errMsg) else: with lineNumbersFileHandler: lineNumbers = lineNumbersFileHandler.readline().strip().split() lineNumbers = [int(lineNumber) for lineNumber in lineNumbers] return lineNumbers
def readProjectConfigFile(location): """ Reads project configuration information from the XML file provided. Arguments: location: Location of the XML file that contains project configuration information. Returns: :class:`~gametime.projectConfiguration.ProjectConfiguration` object that contains information from the XML file whose location is provided. """ logger.info("Reading project configuration in %s..." % location) if not os.path.exists(location): errMsg = "Cannot find project configuration file: %s" % location raise GameTimeError(errMsg) try: projectConfigDom = minidom.parse(location) except EnvironmentError as e: errMsg = "Error reading from project configuration file: %s" % e raise GameTimeError(errMsg) # Check that the root element is properly named. rootNode = projectConfigDom.documentElement if rootNode.tagName != 'gametime-project': raise GameTimeError("The root element in the XML file should be " "named `gametime-project'.") # Check that no child element of the root element has an illegal tag. rootChildNodes = [ node for node in rootNode.childNodes if node.nodeType == node.ELEMENT_NODE ] for childNode in rootChildNodes: childNodeTag = childNode.tagName if childNodeTag not in ["file", "preprocess", "analysis", "debug"]: raise GameTimeError("Unrecognized tag: %s" % childNodeTag) # Find the directory that contains the project configuration XML file. projectConfigDir = os.path.dirname(os.path.abspath(location)) # Initialize the instantiation variables for # the ProjectConfiguration object. locationFile, func = "", "" startLabel, endLabel = "", "" included, merged, inlined, unrollLoops = [], [], [], False randomizeInitialBasis = False maximumErrorScaleFactor = 10 determinantThreshold, maxInfeasiblePaths = 0.001, 100 modelAsNestedArrays, preventBasisRefinement = False, False ilpSolverName, smtSolverName = "", "" # Process information about the file to be analyzed. fileNode = (projectConfigDom.getElementsByTagName("file"))[0] for node in fileNode.childNodes: if node.nodeType == node.ELEMENT_NODE: nodeText = _getText(node) nodeTag = node.tagName if nodeTag == "location": locationFile = \ os.path.normpath(os.path.join(projectConfigDir, nodeText)) elif nodeTag == "analysis-function": func = nodeText elif nodeTag == "start-label": startLabel = nodeText elif nodeTag == "end-label": endLabel = nodeText else: raise GameTimeError("Unrecognized tag: %s" % nodeTag) # Process the preprocessing variables and flags. preprocessingNode = \ (projectConfigDom.getElementsByTagName("preprocess"))[0] for node in preprocessingNode.childNodes: if node.nodeType == node.ELEMENT_NODE: nodeText = _getText(node) nodeTag = node.tagName if nodeTag == "unroll-loops": unrollLoops = True elif nodeTag == "include": if nodeText != "": included = getDirPaths(nodeText, projectConfigDir) elif nodeTag == "merge": if nodeText != "": merged = getFilePaths(nodeText, projectConfigDir) elif nodeTag == "inline": if nodeText != "": inlined = getFuncNames(nodeText) else: raise GameTimeError("Unrecognized tag: %s" % nodeTag) # Process the analysis variables and flags. analysisNode = (projectConfigDom.getElementsByTagName("analysis"))[0] for node in analysisNode.childNodes: if node.nodeType == node.ELEMENT_NODE: nodeText = _getText(node) nodeTag = node.tagName if nodeTag == "randomize-initial-basis": randomizeInitialBasis = True elif nodeTag == "maximum-error-scale-factor": maximumErrorScaleFactor = float(nodeText) elif nodeTag == "determinant-threshold": determinantThreshold = float(nodeText) elif nodeTag == "max-infeasible-paths": maxInfeasiblePaths = int(nodeText) elif nodeTag == "model-as-nested-arrays": modelAsNestedArrays = True elif nodeTag == "prevent-basis-refinement": preventBasisRefinement = True elif nodeTag == "ilp-solver": ilpSolverName = nodeText elif nodeTag == "smt-solver": smtSolverName = nodeText else: raise GameTimeError("Unrecognized tag: %s" % nodeTag) # Initialize the instantiation variables for the # DebugConfiguration object. keepCilTemps, dumpIr, keepIlpSolverOutput = False, False, False dumpInstructionTrace, dumpPath, dumpAllPaths = False, False, False dumpSmtTrace, dumpAllQueries = False, False keepParserOutput, keepSimulatorOutput = False, False # Process the debug flags. debugNode = (projectConfigDom.getElementsByTagName("debug"))[0] for node in debugNode.childNodes: if node.nodeType == node.ELEMENT_NODE: nodeText = _getText(node) nodeTag = node.tagName if nodeTag == "keep-cil-temps": keepCilTemps = True elif nodeTag == "dump-ir": dumpIr = True elif nodeTag == "keep-ilp-solver-output": keepIlpSolverOutput = True elif nodeTag == "dump-instruction-trace": dumpInstructionTrace = True elif nodeTag == "dump-path": dumpPath = True elif nodeTag == "dump-all-paths": dumpAllPaths = True elif nodeTag == "dump-smt-trace": dumpSmtTrace = True elif nodeTag == "dump-all-queries": dumpAllQueries = True elif nodeTag == "keep-parser-output": keepParserOutput = True elif nodeTag == "keep-simulator-output": keepSimulatorOutput = True else: raise GameTimeError("Unrecognized tag: %s" % nodeTag) # Instantiate a DebugConfiguration object. debugConfig = DebugConfiguration(keepCilTemps, dumpIr, keepIlpSolverOutput, dumpInstructionTrace, dumpPath, dumpAllPaths, dumpSmtTrace, dumpAllQueries, keepParserOutput, keepSimulatorOutput) # We have obtained all the information we need from the XML # file provided. Instantiate a ProjectConfiguration object. projectConfig = ProjectConfiguration( locationFile, func, smtSolverName, startLabel, endLabel, included, merged, inlined, unrollLoops, randomizeInitialBasis, maximumErrorScaleFactor, determinantThreshold, maxInfeasiblePaths, modelAsNestedArrays, preventBasisRefinement, ilpSolverName, debugConfig) logger.info("Successfully loaded project.") logger.info("") return projectConfig
def writeToXmlFile(self, locationXmlFile=None): """ Writes the project configuration information to an XML file. Arguments: locationXmlFile: Location of the XML file. If this is not provided, the XML file will be located in the temporary directory where GameTime stores its temporary files. """ locationXmlFile = locationXmlFile or self.locationXmlFile xmlDoc = minidom.Document() # Begin the construction of the XML node tree with the root node. projectRoot = xmlDoc.createElement("gametime-project") xmlDoc.appendChild(projectRoot) # Create the XML node that stores information about # the file to be analyzed. fileNode = xmlDoc.createElement("file") projectRoot.appendChild(fileNode) locationNode = xmlDoc.createElement("location") locationNode.appendChild(xmlDoc.createTextNode(self.locationOrigFile)) fileNode.appendChild(locationNode) funcNode = xmlDoc.createElement("analysis-function") funcNode.appendChild(xmlDoc.createTextNode(self.func)) fileNode.appendChild(funcNode) startLabelNode = xmlDoc.createElement("start-label") startLabelNode.appendChild(xmlDoc.createTextNode(self.startLabel)) fileNode.appendChild(startLabelNode) endLabelNode = xmlDoc.createElement("end-label") endLabelNode.appendChild(xmlDoc.createTextNode(self.endLabel)) fileNode.appendChild(endLabelNode) # Create the XML node that stores the preprocessing # variables and flags. preprocessingNode = xmlDoc.createElement("preprocess") projectRoot.appendChild(preprocessingNode) includeNode = xmlDoc.createElement("include") includeNode.appendChild(xmlDoc.createTextNode(" ".join(self.included))) preprocessingNode.appendChild(includeNode) mergeNode = xmlDoc.createElement("merge") mergeNode.appendChild(xmlDoc.createTextNode(" ".join(self.merged))) preprocessingNode.appendChild(mergeNode) inlineNode = xmlDoc.createElement("inline") inlineNode.appendChild(xmlDoc.createTextNode(" ".join(self.inlined))) preprocessingNode.appendChild(inlineNode) if self.UNROLL_LOOPS: unrollLoopsNode = xmlDoc.createElement("unroll-loops") preprocessingNode.appendChild(unrollLoopsNode) # Create the XML node that stores the analysis variables and flags. analysisNode = xmlDoc.createElement("analysis") projectRoot.appendChild(analysisNode) if self.RANDOMIZE_INITIAL_BASIS: randomizeInitialBasisNode = \ xmlDoc.createElement("randomize-initial-basis") analysisNode.appendChild(randomizeInitialBasisNode) maximumErrorScaleFactorNode = \ xmlDoc.createElement("maximum-error-scale-factor") basisErrorNode = xmlDoc.createTextNode("%g" % self.MAXIMUM_ERROR_SCALE_FACTOR) maximumErrorScaleFactorNode.appendChild(basisErrorNode) determinantThresholdNode = \ xmlDoc.createElement("determinant-threshold") thresholdAmountNode = xmlDoc.createTextNode("%g" % self.DETERMINANT_THRESHOLD) determinantThresholdNode.appendChild(thresholdAmountNode) analysisNode.appendChild(determinantThresholdNode) maxInfeasiblePathsNode = xmlDoc.createElement("max-infeasible-paths") numInfeasiblePathsNode = \ xmlDoc.createTextNode("%g" % self.MAX_INFEASIBLE_PATHS) maxInfeasiblePathsNode.appendChild(numInfeasiblePathsNode) analysisNode.appendChild(maxInfeasiblePathsNode) if self.MODEL_AS_NESTED_ARRAYS: modelAsNestedArraysNode = \ xmlDoc.createElement("model-as-nested-arrays") analysisNode.appendChild(modelAsNestedArraysNode) if self.PREVENT_BASIS_REFINEMENT: preventBasisRefinementNode = \ xmlDoc.createElement("prevent-basis-refinement") analysisNode.appendChild(preventBasisRefinementNode) ilpSolverNode = xmlDoc.createElement("ilp-solver") ilpSolverName = pulpHelper.getIlpSolverName(self.ilpSolver) ilpSolverNode.appendChild(xmlDoc.createTextNode(ilpSolverName)) analysisNode.appendChild(ilpSolverNode) smtSolverNode = xmlDoc.createElement("smt-solver") smtSolverNode.appendChild(xmlDoc.createTextNode(str(self.smtSolver))) analysisNode.appendChild(smtSolverNode) # Create the XML node that stores the debug flags. debugNode = xmlDoc.createElement("debug") projectRoot.appendChild(debugNode) if self.debugConfig.KEEP_CIL_TEMPS: keepCilTempsNode = xmlDoc.createElement("keep-cil-temps") debugNode.appendChild(keepCilTempsNode) if self.debugConfig.DUMP_IR: dumpIrNode = xmlDoc.createElement("dump-ir") debugNode.appendChild(dumpIrNode) if self.debugConfig.KEEP_ILP_SOLVER_OUTPUT: keepIlpSolverOutputNode = \ xmlDoc.createElement("keep-ilp-solver-output") debugNode.appendChild(keepIlpSolverOutputNode) if self.debugConfig.DUMP_PATH: dumpPathNode = xmlDoc.createElement("dump-path") debugNode.appendChild(dumpPathNode) if self.debugConfig.DUMP_ALL_PATHS: dumpAllPathsNode = xmlDoc.createElement("dump-all-paths") debugNode.appendChild(dumpAllPathsNode) if self.debugConfig.DUMP_INSTRUCTION_TRACE: dumpInstrTraceNode = xmlDoc.createElement("dump-instruction-trace") debugNode.appendChild(dumpInstrTraceNode) if self.debugConfig.DUMP_SMT_TRACE: dumpSmtTraceNode = xmlDoc.createElement("dump-smt-trace") debugNode.appendChild(dumpSmtTraceNode) if self.debugConfig.DUMP_ALL_QUERIES: dumpAllQueriesNode = xmlDoc.createElement("dump-all-queries") debugNode.appendChild(dumpAllQueriesNode) if self.debugConfig.KEEP_PARSER_OUTPUT: keepParserOutputNode = xmlDoc.createElement("keep-parser-output") debugNode.appendChild(keepParserOutputNode) if self.debugConfig.KEEP_SIMULATOR_OUTPUT: keepSimulatorOutputNode = \ xmlDoc.createElement("keep-simulator-output") debugNode.appendChild(keepSimulatorOutputNode) try: locationHandler = open(locationXmlFile, "w") except EnvironmentError as e: errMsg = ("Error creating the project configuration " "XML file: %s") % e raise GameTimeError(errMsg) else: with locationHandler: # Create the pretty-printed text version of the XML node tree. prettyPrinted = xmlDoc.toprettyxml(indent=" ") locationHandler.write(prettyPrinted)