#include <stdint.h>
#include <stdlib.h>
#include "../extlib-constbv/constantbv.h"
+#include "RunTimes.h"
/*****************************************************************************
* LIST OF CLASSES DECLARED IN THIS FILE:
bool CheckMap(ASTNodeMap* VarConstMap,
const ASTNode& key, ASTNode& output);
+ RunTimes runTimes;
//substitution
bool CheckSubstitutionMap(const ASTNode& a, ASTNode& output);
--- /dev/null
+//Hold the runtime statistics. E.g. how long was spent in simplification.
+//The times don't add up to the runtime, because we allow multiple times to
+//be counted simultaneously. For example, the current Transform()s call
+//Simplify_TopLevel, so inside simplify time will be couunted towards both
+//Simplify_TopLevel & Transform.
+
+// This is intended as a low overhead profiling class. So it can be always run.
+
+#include "RunTimes.h"
+#include <cassert>
+#include <sys/time.h>
+#include <sstream>
+#include <iostream>
+#include <utility>
+
+
+std::string RunTimes::CategoryNames[] = { "Transforming", "Simplify Top Level", "Parsing","Transforming" , "CNF Conversion", "Bit Blasting", "Solving"};
+
+namespace BEEV
+{
+ void FatalError(const char * str);
+}
+
+
+long RunTimes::getCurrentTime()
+{
+ timeval t;
+ gettimeofday(&t, NULL);
+ return (1000 * t.tv_sec) + (t.tv_usec / 1000);
+}
+
+void RunTimes::print()
+{
+ if (0 != category_stack.size())
+ BEEV::FatalError("category stack is not yet emptuy");
+
+ std::ostringstream result;
+ result << "statistics\n";
+ std::map<Category, int>::const_iterator it1 = counts.begin();
+ std::map<Category, long>::const_iterator it2 = times.begin();
+
+ while (it1 != counts.end())
+ {
+ result << " " << CategoryNames[it1->first] << ": " << it1->second;
+ if ((it2 = times.find(it1->first)) != times.end())
+ result << " [" << it2->second << "ms]";
+ result << std::endl;
+ it1++;
+ }
+
+ std::cerr << result.str();
+ // iterator
+}
+
+void RunTimes::addTime(Category c, long milliseconds)
+{
+ std::map<Category, long>::iterator it;
+ if ((it = times.find(c)) == times.end())
+ {
+ times[c] = milliseconds;
+ }
+ else
+ {
+ it->second += milliseconds;
+ }
+
+}
+
+void RunTimes::addCount(Category c)
+{
+ std::map<Category, int>::iterator it;
+ if ((it = counts.find(c)) == counts.end())
+ {
+ counts[c] = 1;
+ }
+ else
+ {
+ it->second++;
+ }
+}
+
+void RunTimes::stop(Category c)
+{
+ Element e = category_stack.top();
+ category_stack.pop();
+ if (e.first != c)
+ {
+ std::cerr << e.first;
+ std::cerr << c;
+ BEEV::FatalError("Don't match");
+ }
+ addTime(c, getCurrentTime() - e.second);
+ addCount(c);
+}
+
+void RunTimes::start(Category c)
+{
+ category_stack.push(std::make_pair(c, getCurrentTime()));
+}
--- /dev/null
+#ifndef RUNTIMES_H
+#define RUNTIMES_H
+
+#include <stack>
+#include <map>
+#include <string>
+
+class RunTimes
+{
+public:
+ enum Category
+ { // BE VERY CAREFUL> Update the Category Names to match.
+ Transforming = 0, SimplifyTopLevel, Parsing, TransformFormulaTopLevel, CNFConversion, BitBlasting, Solving
+ };
+ static std::string CategoryNames[];
+
+ typedef std::pair<Category, long> Element;
+
+private:
+ RunTimes& operator =(const RunTimes&);
+ RunTimes(const RunTimes& other);
+
+ std::map<Category, int> counts;
+ std::map<Category, long> times;
+ std::stack<Element> category_stack;
+
+ // millisecond precision timer.
+ long getCurrentTime();
+ void addTime(Category c, long milliseconds);
+
+public:
+
+ void addCount(Category c);
+ void start(Category c);
+ void stop(Category c);
+ void print();
+
+ RunTimes(){}
+
+ void clear()
+ {
+ counts.clear();
+ times.clear();
+ category_stack.empty();
+ }
+
+
+
+};
+
+#endif
// up the cache that the others use.
ASTNode BeevMgr::TransformFormula_TopLevel(const ASTNode& form)
{
+ runTimes.start(RunTimes::TransformFormulaTopLevel);
+
assert(TransformMap == NULL);
TransformMap = new ASTNodeMap(100);
ASTNode result = TransformFormula(form);
TransformMap->clear();
delete TransformMap;
TransformMap = NULL;
+
+ runTimes.stop(RunTimes::TransformFormulaTopLevel);
+
return result;
}
string functionToSMTLIBName(const BEEV::Kind k);
void SMTLIB_Print1(ostream& os, const BEEV::ASTNode n, int indentation, bool letize);
- void printVarDeclsToStream( const BeevMgr mgr, ostream &os);
+ void printVarDeclsToStream( const BeevMgr& mgr, ostream &os);
// Initial version intended to print the whole thing back.
void SMTLIB_PrintBack(ostream &os, const ASTNode& n) {
os << ")" << endl;
}
- void printVarDeclsToStream( const BeevMgr mgr, ostream &os) {
+ void printVarDeclsToStream( const BeevMgr& mgr, ostream &os) {
for(ASTVec::const_iterator i = mgr.ListOfDeclaredVars.begin(),iend=mgr.ListOfDeclaredVars.end();i!=iend;i++) {
const BEEV::ASTNode& a = *i;
FatalError("Initial allocation of memory failed.");
}
+ bool quick_statistics_flag=false;
+
//populate the help string
helpstring += "STP version: " + version + "\n\n";
helpstring += "-a : switch optimizations off (optimizations are ON by default)\n";
helpstring += "-p : print counterexample\n";
helpstring += "-r : switch refinement off (optimizations are ON by default)\n";
helpstring += "-s : print function statistics\n";
+ helpstring += "-t : print quick statistics\n";
helpstring += "-v : print nodes \n";
helpstring += "-w : switch wordlevel solver off (optimizations are ON by default)\n";
helpstring += "-x : flatten nested XORs\n";
case 's' :
stats_flag = true;
break;
+ case 't':
+ quick_statistics_flag = true;
+ break;
case 'u':
arraywrite_refinement_flag = false;
break;
GlobalBeevMgr = new BeevMgr();
ASTVec * AssertsQuery = new ASTVec;
+ GlobalBeevMgr->runTimes.start(RunTimes::Parsing);
if (smtlib_parser_flag)
{
smtparse((void*)AssertsQuery);
{
cvcparse((void*)AssertsQuery);
}
+ GlobalBeevMgr->runTimes.stop(RunTimes::Parsing);
ASTNode asserts = (*(ASTVec*)AssertsQuery)[0];
ASTNode query = (*(ASTVec*)AssertsQuery)[1];
} //end of PrintBack if
SOLVER_RETURN_TYPE ret = GlobalBeevMgr->TopLevelSAT(asserts, query);
+ if (quick_statistics_flag)
+ GlobalBeevMgr->runTimes.print();
GlobalBeevMgr->PrintOutput(ret);
return 0;
}//end of Main
BeevMgr::SimplifyFormula_TopLevel(const ASTNode& b,
bool pushNeg, ASTNodeMap* VarConstMap)
{
+ runTimes.start(RunTimes::SimplifyTopLevel);
ResetSimplifyMaps();
-
if (smtlib_parser_flag)
BuildReferenceCountMap(b);
ASTNode out = SimplifyFormula(b, pushNeg, VarConstMap);
ResetSimplifyMaps();
+ runTimes.stop(RunTimes::SimplifyTopLevel);
return out;
}
BeevMgr::ClauseList* convertToCNF(const ASTNode& varphi)
{
+ varphi.GetBeevMgr().runTimes.start(RunTimes::CNFConversion);
scanFormula(varphi, true);
ASTNode dummy_true_var = bm->CreateSymbol("*TrueDummy*");
BeevMgr::ClauseList* defs = SINGLETON(dummy_true_var);
defs->insert(defs->begin() + 1, top->begin(), top->end());
cleanup(varphi);
+ varphi.GetBeevMgr().runTimes.stop(RunTimes::CNFConversion);
return defs;
}
const ASTNode& modified_input,
const ASTNode& original_input)
{
+ runTimes.start(RunTimes::BitBlasting);
ASTNode BBFormula = BBForm(modified_input);
+ runTimes.stop(RunTimes::BitBlasting);
+
CNFMgr* cm = new CNFMgr(this);
ClauseList* cl = cm->convertToCNF(BBFormula);
if (stats_flag)
#include "../AST/AST.h"
#include "../simplifier/bvsolver.h"
#include "../sat/sat.h"
+#include "../AST/RunTimes.h"
namespace BEEV
{
//printf("##################################################\n");
ASTNodeStats("after pure substitution: ", simplified_solved_InputToSAT);
+
simplified_solved_InputToSAT =
SimplifyFormula_TopLevel(simplified_solved_InputToSAT, false);
+
ASTNodeStats("after simplification: ", simplified_solved_InputToSAT);
}
}
res = CallSAT_ResultCheck(newS, simplified_solved_InputToSAT, orig_input);
+
if (SOLVER_UNDECIDED != res)
{
CountersAndStats("print_func_stats");