metaSMT 2
|
00001 #include "CUDD_Context.hpp" 00002 #include <cstdlib> 00003 00004 #include <boost/format.hpp> 00005 #include <boost/random/uniform_int.hpp> 00006 #include <boost/random/mersenne_twister.hpp> 00007 00008 namespace metaSMT { 00009 namespace solver { 00010 00011 class CUDD_Distributed : public CUDD_Context 00012 { 00013 00014 public: 00015 00016 CUDD_Distributed () { 00017 reset(); 00018 } 00019 00020 bool solve() { 00021 BDD complete =_assertions & _assumptions; 00022 bool ret = complete != _manager.bddZero(); 00023 _assumptions = _manager.bddOne(); 00024 //printDD(complete.getNode(),"BDD.dot"); 00025 if(ret) { 00026 store_solution( complete.getNode() ); 00027 reset(); 00028 } 00029 return ret; 00030 } 00031 00032 private: 00033 std::map<DdNode *, unsigned> map_0; 00034 std::map<DdNode *, unsigned> map_1; 00035 00036 void reset() { 00037 00038 map_0.clear(); 00039 map_1.clear(); 00040 00041 map_0 [_manager.bddZero().getNode()] = 1; 00042 map_1 [_manager.bddZero().getNode()] = 0; 00043 map_0 [_manager.bddOne().getNode()] = 0; 00044 map_1 [_manager.bddOne().getNode()] = 1; 00045 } 00046 unsigned distance(DdNode *parent, DdNode *child) { 00047 int i_1 = Cudd_ReadPerm(_manager.getManager(),Cudd_Regular(parent)->index); 00048 int i_2 = (Cudd_IsConstant(child)) ? _manager.ReadSize() : Cudd_ReadPerm(_manager.getManager(), Cudd_Regular(child)->index); 00049 //std::cout << boost::format( "distance(v%d,v%d) = %d - %d = %d\n") 00050 // % parent->index % child->index % i_2 % i_1 % (i_2 - i_1); 00051 return i_2 - i_1; 00052 } 00053 00054 unsigned skipped ( DdNode *parent, DdNode *child) { 00055 unsigned t = distance (parent, child); 00056 if(t > 0) return t-1; 00057 else return 0; 00058 } 00059 00060 unsigned count_0 (DdNode *root) { 00061 if( Cudd_IsComplement(root)) { 00062 DdNode * comp = Cudd_Regular(root); 00063 //std::cout << boost::format("count_0(v%d)=count_1( ~v%d )\n") % root->index% comp->index; 00064 return count_1(comp); 00065 } 00066 //std::cout << boost::format("count_0(v%d)\n") % root->index; 00067 std::map<DdNode *, unsigned>::iterator iter = map_0.find(root); 00068 if(iter != map_0.end()) { 00069 //std::cout << boost::format("count_0(v%d) = %d\n") % root->index % iter->second; 00070 return iter->second; 00071 } else { 00072 00073 unsigned ret = count_0 ( Cudd_T( root ) )*( 1ull << skipped( root, Cudd_T(root) ) ) ; 00074 //std::cout << "then count is " << ret << std::endl; 00075 ret += count_0 (Cudd_E(root)) * ( 1ull << skipped( root, Cudd_E( root ) ) ); 00076 //std::cout << "after else count is " << ret << std::endl; 00077 map_0.insert( std::make_pair(root,ret) ); 00078 //std::cout << boost::format("count_0(v%d) = %d\n") % root->index % ret; 00079 return ret; 00080 } 00081 } 00082 00083 unsigned count_1 (DdNode *root) { 00084 if( Cudd_IsComplement(root)) { 00085 DdNode * comp = Cudd_Regular(root); 00086 //std::cout << boost::format("count_1(v%d)=count_0( ~v%d )\n") % root->index% comp->index; 00087 return count_0(comp); 00088 } 00089 //std::cout << boost::format("count_1(v%d)\n") % root->index; 00090 std::map<DdNode *, unsigned>::iterator iter = map_1.find(root); 00091 00092 if(iter != map_1.end()) { 00093 //std::cout << boost::format("count_1(v%d) = %d\n") % root->index % iter->second; 00094 return iter->second; 00095 } else { 00096 unsigned ret = count_1 ( Cudd_T( root ) )*( 1ull << skipped( root, Cudd_T(root) ) ) ; 00097 //std::cout << "then count is " << ret << std::endl; 00098 ret += count_1 (Cudd_E(root)) * ( 1ull << skipped( root, Cudd_E( root ) ) ); 00099 //std::cout << "after else count is " << ret << std::endl; 00100 00101 map_1.insert( std::make_pair(root,ret) ); 00102 //std::cout << boost::format("count_1(v%d) = %d\n") % root->index % ret; 00103 return ret; 00104 00105 } 00106 } 00107 00108 00109 void store_solution ( DdNode * root) { 00110 00111 // clear solution 00112 unsigned size = _manager.ReadSize(); 00113 std::vector< boost::logic::tribool > (size, boost::logic::indeterminate).swap(_solution); 00114 00115 bool negated = false; 00116 00117 while( ! Cudd_IsConstant(root) ) { 00118 00119 //std::cout << "chosing for v" << root->index << " (negated: " << negated << ")" << std::endl; 00120 00121 unsigned cnt_r = 0; 00122 unsigned cnt_t = 0; 00123 negated ^= Cudd_IsComplement( root ); 00124 root = Cudd_Regular(root); 00125 DdNode* child = Cudd_T(root); 00126 if( negated ) { 00127 cnt_r = count_0(root); 00128 cnt_t = count_0(child) << skipped(root, child); 00129 } else { 00130 cnt_r = count_1(root); 00131 cnt_t = count_1(child)<< skipped(root, child); 00132 } 00133 00134 //std::cout << "count: " << cnt_r << " " << cnt_t << std::endl; 00135 00136 boost::uniform_int<unsigned> rnd( 0, cnt_r-1); 00137 unsigned select = rnd(gen); 00138 //std::cout << boost::format("%u %u %u") %select%cnt_r%cnt_t << std::endl; 00139 if(select < cnt_t ) 00140 { 00141 //std::cout << "v" << root->index << " = 1" << std::endl; 00142 _solution[root->index] = true; 00143 root = Cudd_T( root ); 00144 } 00145 else 00146 { 00147 //std::cout << "v" << root->index << " = 0" << std::endl; 00148 _solution[root->index] = false; 00149 root = Cudd_E( root ); 00150 } 00151 } 00152 assert( Cudd_V(root) == 1 ); 00153 } 00154 00155 void printDD(DdNode *root, std::string fileName) { 00156 00157 00158 00159 FILE *file = fopen(fileName.c_str(),"w"); 00160 00161 char **iname = (char**) malloc(sizeof(char *)*_manager.ReadSize()); 00162 for(unsigned i = 0; i < _manager.ReadSize(); ++i) 00163 { 00164 char *name = (char*) malloc(256); 00165 sprintf(name,"v%d", _manager.bddVar(i).NodeReadIndex()); 00166 iname [i] = name; 00167 } 00168 //extern int Cudd_DumpDot (DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp); 00169 Cudd_DumpDot (_manager.getManager(),1,&root,iname, NULL,file); 00170 fclose(file); 00171 } 00172 private: 00173 boost::mt19937 gen; 00174 }; // class CUDD_Distribuded 00175 00176 } //namespace metaSMT 00177 }// namespace solver