@@ -67,6 +67,7 @@ void Oracle::AddSolToCache() {
6767 }
6868 sol_cache.swap (new_cache);
6969 assert (sol_cache.size ()%mult == 0 );
70+ rebuild_cache_lookup ();
7071 }
7172
7273 sol_cache.push_back (255 ); // 0th variable, nonsense
@@ -75,29 +76,115 @@ void Oracle::AddSolToCache() {
7576 sol_cache.push_back (vs[i].phase );
7677 }
7778 assert (sol_cache.size ()%mult == 0 );
79+
80+ // add to lookup
81+ if (cache_lookup_var != 0 ) {
82+ auto val = vs[cache_lookup_var].phase ;
83+ cache_lookup[val].push_back (sol_cache.size ()/mult - 1 );
84+ assert (cache_lookup[0 ].size () + cache_lookup[1 ].size () == sol_cache.size ()/mult);
85+ }
7886 stats.cache_added ++;
7987}
8088
89+ void Oracle::rebuild_cache_lookup () {
90+ const uint32_t mult = vars+1 ;
91+ cache_lookup[0 ].clear ();
92+ cache_lookup[1 ].clear ();
93+ if (cache_lookup_var != 0 ) {
94+ assert (cache_lookup_var < vars+1 );
95+ for (size_t i = 0 ; i < sol_cache.size ()/mult; i++) {
96+ auto val = sol_cache[i*mult + cache_lookup_var];
97+ cache_lookup[val].push_back (i);
98+ }
99+ assert (cache_lookup[0 ].size () + cache_lookup[1 ].size () == sol_cache.size ()/mult);
100+ }
101+ }
102+
81103void Oracle::ClearSolCache () {
82104 sol_cache.clear ();
105+ cache_lookup_var = 0 ;
106+ rebuild_cache_lookup ();
107+ cache_lookup_frequencies.clear ();
83108}
84109
85110bool Oracle::SatByCache (const vector<Lit>& assumps) {
86- // Try all cache lines
87- uint64_t checks = 0 ;
88111 const uint32_t mult = vars+1 ;
89112 assert (sol_cache.size ()%mult == 0 );
90- const uint64_t sz = sol_cache.size ();
91- for (uint64_t i = 0 ; i < sz; i+=mult) {
92- bool ok = true ;
93- // all our assumptions must be in the solution
94- for (const Lit& l : assumps) {
95- checks++;
96- if (sol_cache[i + VarOf (l)] == !IsPos (l)) { ok = false ; break ; }
113+
114+ if (cache_lookup_frequencies.empty ()) {
115+ cache_lookup_frequencies.resize (vars+1 , 0 );
116+ }
117+ for (const Lit& l : assumps) cache_lookup_frequencies[VarOf (l)]++;
118+ if ((stats.sat_by_cache_calls % 1000 == 999 )) {
119+ vector<uint32_t > occs_int (mult, 0 );
120+ const uint64_t sz = sol_cache.size ();
121+ for (uint64_t i = 0 ; i < sz; i+=mult) {
122+ for (uint64_t i2 = 1 ; i2 < mult; i2++) {
123+ occs_int[i2] += sol_cache[i + i2];
124+ }
97125 }
98- if (ok) return true ;
126+ vector<double > occs (mult, 0.0 );
127+ for (uint64_t i = 1 ; i < mult; i++) {
128+ auto & o = occs[i];
129+ o = (double )occs_int[i]/((double )sz/mult);
130+ o = (o < 0.5 ) ? o : (1.0 - o);
131+ }
132+ vector<int > v;
133+ for (int i = 1 ; i <= vars; i++) v.push_back (i);
134+ std::sort (v.begin (), v.end (), [&](int a, int b){
135+ uint64_t fa = (double )cache_lookup_frequencies[a]*occs[a];
136+ uint64_t fb = (double )cache_lookup_frequencies[b]*occs[b];
137+ return fa > fb;
138+ });
139+ cache_lookup_var = v[0 ];
140+ rebuild_cache_lookup ();
99141 }
142+
143+
144+ // Check if cache var is assumps
145+ bool found = false ;
146+ bool val;
147+ if (cache_lookup_var != 0 ) {
148+ for (const auto & l: assumps) {
149+ if (VarOf (l) == cache_lookup_var) {
150+ found = true ;
151+ val = IsPos (l);
152+ break ;
153+ }
154+ }
155+ }
156+
157+ uint64_t checks = 0 ;
158+ if (found) {
159+ for (const auto & idx : cache_lookup[val]) {
160+ bool ok = true ;
161+ // all our assumptions must be in the solution
162+ for (const Lit& l : assumps) {
163+ checks++;
164+ if (sol_cache[idx*mult + VarOf (l)] == !IsPos (l)) { ok = false ; break ; }
165+ }
166+ if (ok) return true ;
167+ }
168+ } else {
169+ const uint64_t sz = sol_cache.size ();
170+ for (uint64_t i = 0 ; i < sz; i+=mult) {
171+ bool ok = true ;
172+ // all our assumptions must be in the solution
173+ for (const Lit& l : assumps) {
174+ checks++;
175+ if (sol_cache[i + VarOf (l)] == !IsPos (l)) { ok = false ; break ; }
176+ }
177+ if (ok) return true ;
178+ }
179+ }
180+ stats.sat_by_cache_calls ++;
100181 stats.mems += checks/20 ;
182+ if (stats.sat_by_cache_calls % 100 == 99 ) {
183+ cout << " found: " << found << " cache var: " << cache_lookup_var
184+ << " orig sz: " << sol_cache.size ()/mult
185+ << " cache size: " << cache_lookup[0 ].size () << " -- " << cache_lookup[1 ].size ()
186+ << endl;
187+ }
101188
102189 // Not in the cache
103190 return false ;
0 commit comments