forked from alexander-nadel/intel_sat_solver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTopi.hpp
3114 lines (2708 loc) · 138 KB
/
Topi.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright(C) 2021-2022 Intel Corporation
// SPDX - License - Identifier: MIT
#pragma once
#include <span>
#include <limits>
#include <bit>
#include <string>
#include <any>
#include <fstream>
#include <queue>
#include <memory>
#include <tuple>
#include "ToporExternalTypes.hpp"
#include "ToporBitArrayBuffer.hpp"
#include "ToporDynArray.hpp"
#include "ToporBitArray.hpp"
#include "ToporVector.hpp"
#include "TopiParams.hpp"
#include "TopiVarScores.hpp"
#include "ToporWinAverage.hpp"
#include "SetInScope.h"
using namespace std;
namespace Topor
{
// To be used by compressed buffer management
constexpr array<uint32_t, 32> lowestClsSizePerBits = []
{
array<uint32_t, 32> lcspb = {};
lcspb[0] = 3;
for (uint8_t currBits = 1; currBits < 32; ++currBits)
{
// 2^n - n + 3
lcspb[currBits] = ((uint32_t)1 << currBits) - currBits + 3;
}
return lcspb;
}();
template <typename T>
inline std::string HexStr(T val, size_t width = sizeof(T) * 2)
{
stringstream ss;
ss << setfill('0') << setw(width) << hex << (val | 0);
return ss.str();
}
// The main solver class
template <typename TLit, typename TUInd, bool Compress>
class CTopi
{
public:
// varNumHint is the expected number of variables -- a non-mandatory hint, which, if provided correctly, helps the solver initialize faster
CTopi(TLit varNumHint = 0);
// DUMPS
void AddUserClause(const span<TLit> c);
// DUMPS
TToporReturnVal Solve(const span<TLit> userAssumps = {}, pair<double, bool> toInSecIsCpuTime = make_pair(numeric_limits<double>::max(), true), uint64_t confThr = numeric_limits<uint64_t>::max());
bool IsAssumptionRequired(size_t assumpInd);
TToporLitVal GetValue(TLit l) const;
TLit GetLitDecLevel(TLit l) const;
std::vector<TToporLitVal> GetModel() const;
TToporStatistics<TLit, TUInd> GetStatistics() const;
string GetParamsDescr() const;
// Set a parameter value; using double for avalue, since it encompasses all the arithmetic types, which can be used for parameters, that is:
// Signed and unsigned integers of at most 32 bits and floating-points of at most the size of a C++ double
// DUMPS
void SetParam(const string& paramName, double newVal);
// Is there an error?
bool IsError() const;
// Get the explanation for the current status (returns the empty string, if there is no error and verbosity is off)
string GetStatusExplanation() const { return IsError() || m_ParamVerbosity > 0 ? m_StatusExplanation : ""; }
// Dump DRAT, if invoked
void DumpDrat(ofstream& openedDratFile, bool isDratBinary) { m_OpenedDratFile = &openedDratFile; m_IsDratBinary = isDratBinary; }
// Set callback: stop-now
void SetCbStopNow(TCbStopNow CbStopNow) { M_CbStopNow = CbStopNow; }
// Interrupt now
void InterruptNow() { m_InterruptNow = true; }
// Set callback: new-learnt-clause
void SetCbNewLearntCls(TCbNewLearntCls<TLit> CbNewLearntCls) { M_CbNewLearntCls = CbNewLearntCls; }
// Boost the score of the variable v by mult
// DUMPS
void BoostScore(TLit vExternal, double mult = 1.0);
// Fix the polarity of the variable |l| to l
// onlyOnce = false: change until ClearUserPolarityInfo(|l|) is invoked (or, otherwise, forever)
// onlyOnce = true: change only once right now
// DUMPS
void FixPolarity(TLit lExternal, bool onlyOnce = false);
// Create an internal literal for l *now*
// DUMPS
void CreateInternalLit(TLit l);
// Clear any polarity information of the variable v, provided by the user (so, the default solver's heuristic will be used to determine polarity)
// DUMPS
void ClearUserPolarityInfo(TLit vExternal);
// Backtrack to the end of decLevel; the 2nd parameter is required for statistics only
// DUMPS
void Backtrack(TLit decLevel, bool isBCPBacktrack = false, bool reuseTrail = false, bool isAPICall = false);
// Changing the configuration to # configNum, so that every configNum generates a unique configuration
// This is used for enabling different configs in parallel solving
// DUMPS
string ChangeConfigToGiven(uint16_t configNum);
// Set the relevant data for a higher-level parallel solver
void SetParallelData(unsigned threadId, std::function<void(unsigned threadId, int lit)> ReportUnitClause, std::function<int(unsigned threadId, bool reinit)> GetNextUnitClause);
protected:
/*
* Internal types
*/
static constexpr bool Standard = !Compress;
// The number of literal-entries in an index-entry
static constexpr size_t LitsInInd = sizeof(TUInd) / sizeof(TLit);
// The TLit type, representing the external literals, unsigned
// Will be used for storing internal literals, whose sign is determined by the LSB, rather than the MSB
using TULit = make_unsigned<TLit>::type;
static_assert(numeric_limits<TULit>::digits == numeric_limits<TLit>::digits + 1);
// Bad literal
TULit static constexpr BadULit = 0;
// TUL is used to hold unsigned integers, whose number is not greater than that of the literaks; used only for code clarity
using TUL = TULit;
// TUVar is used to hold variables; used only for code clarity
using TUVar = TULit;
// TUV is used to hold unsigned integers, whose number is not greater than that of the variables; used only for code clarity
using TUV = TUVar;
// Bad variable
TULit static constexpr BadUVar = 0;
// counter type for discovering duplicates, tautologies, contradictions etc., e.g., in incoming clauses and assumptions
// In the context of handling new clauses,
// we did some tests and found that int32_t for the counter works better than int64_t, int16_t (both are 2x slower) and int8_t (significantly slower)
// We also tested options using bit-arrays CBitArray<2> and CBitArrayAligned<2> with memset-0 after each clause,
// but the former is much slower than the current implementation, while the latter is impossibly slow.
typedef int32_t TCounterType;
static_assert(is_signed<TCounterType>::value);
// A span of internal literals (TULit)
using TSpanTULit = span<CTopi<TLit, TUInd, Compress>::TULit>;
/*
* Parameters
*/
// Contains a map from parameter name to parameter description & function to set it for every parameter
// Every parameter adds itself to the list, so we don't have to do it manually in this class
// To add a parameter, it suffices to declare it below, c'est tout!
CTopiParams m_Params;
// The following semantics would have been better,
// but double template parameters are not supported even by gcc 10.2
// CTopiParam template class semantics: <type, initVal, minVal, maxVal>, where:
// type must be an arithmetic type, where a floating-point type must fit into a double, and an integer-type must fit into half-a-double
// minVal <= initVal <= maxVal
// To find the mode values using a regular expression: (, *){(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*),(.*)}(,| )
// Replace expression, used last time to create a new mode from mode 2 (when there was one less mode): $1{$2,$3,$4,$5,$6,$7,$8,$9,$4}$10
// The special mode meta-parameter; Every parameter can be provided either one single default or a separate default for each mode (in an array)
CTopiParam<TModeType> m_Mode = { m_Params, m_ModeParamName, "The mode (0: Unweighted MaxSAT; 1: FLA; 2: FSN; 3: MF2S; 4: LAR; 5: Weighted MaxSAT; 6: FRU; 7: SN1, 8: EBB)", 0, 0, m_Modes - 1 };
// Parameters: verbosity
CTopiParam<uint8_t> m_ParamVerbosity = { m_Params, "/verbosity/level", "Verbosity level (0: silent; 1: basic statistics; 2: trail&conflict debugging; 3: extensive debugging)", 0, 0, 3};
CTopiParam<uint32_t> m_ParamHeavyVerbosityStartConf = { m_Params, "/verbosity/verbosity_start_conf", "Meaningful only if /verbosity/level>1: print-out at level > 1 starting with the provided conflicts number", 0 };
CTopiParam<uint32_t> m_ParamStatPrintOutConfs = { m_Params, "/verbosity/print_out_confs", "Meaningful only if /verbosity/level>0: the rate of print-outs in #conflicts", 2000, 1 };
CTopiParam<bool> m_ParamPrintMemoryProfiling = { m_Params, "/verbosity/print_mem_prof", "Print-out memory profiling info", false };
// Parameters: timeout
CTopiParam<double> m_ParamOverallTimeout = { m_Params, "/timeout/global", "An overall global timeout for Topor lifespan: Topor will be unusable after reaching this timeout (note that one can also provide a Solve-specific timeout as a parameter to Solve)", numeric_limits<double>::max(), numeric_limits<double>::epsilon() };
CTopiParam<bool> m_ParamOverallTimeoutIsCpu = { m_Params, "/timeout/global_is_cpu", "Is the overall global timeout (if any) for Topor lifespan CPU (or, otherwise, Wall)", false };
// Parameters: decision
CTopiParam<uint8_t> m_ParamInitPolarityStrat = { m_Params, "/decision/polarity/init_strategy", "The initial polarity for a new variable: 0: negative; 1: positive; 2: random", {1, 1, 1, 1, 1, 2, 1, 1, 1}, 0, 2 };
CTopiParam<uint8_t> m_ParamPolarityStrat = { m_Params, "/decision/polarity/strategy", "How to set the polarity for a non-forced variable: 0: phase saving; 1: random", 0, 0, 1 };
CTopiParam<uint32_t> m_ParamPolarityFlipFactor = { m_Params, "/decision/polarity/flip_factor", "If non-0, every N's polarity selection will be flipped", 0};
CTopiParam<double> m_ParamVarActivityInc = { m_Params, "/decision/vsids/var_activity_inc", "Variable activity bumping factor's initial value: m_PosScore[v].m_Score += m_VarActivityInc is carried out for every variable visited during a conflict (hard-coded to 1.0 in Glucose-based solvers)", {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.8, 1.0}, 0.0 };
CTopiParam<double> m_ParamVarActivityIncDecay = { m_Params, "/decision/vsids/var_activity_inc_decay", "After each conflict, the variable activity bumping factor is increased by multiplication by 1/m_ParamVarActivityIncDecay (the initial value is provided in the parameter): m_ParamVarActivityInc *= (1 / m_ParamVarActivityIncDecay), where it's 0.8 in Glucose-based solvers and 0.95 in Minisat", {0.95, 0.8, 0.8, 0.8, 0.8, 0.925, 0.8, 0.95, 0.925}, numeric_limits<double>::epsilon(), 1.0 };
CTopiParam<bool> m_ParamVarActivityIncDecayReinitN = { m_Params, "/decision/vsids/var_activity_inc_decay_reinit_n", "Re-initialize /decision/vsids/var_activity_inc_decay before normal incremental Solve?", {true, false, false, false, false, false, false, true, false} };
CTopiParam<bool> m_ParamVarActivityIncDecayReinitS = { m_Params, "/decision/vsids/var_activity_inc_decay_reinit_s", "Re-initialize /decision/vsids/var_activity_inc_decay before short incremental Solve?", {true, false, false, false, false, true, false, false, false} };
CTopiParam<uint32_t> m_ParamVarActivityIncDecayStopReinitSInv = { m_Params, "/decision/vsids/var_activity_inc_decay_stop_reinit_s_inv", "The first short incremental invocation to stop re-initializing /decision/vsids/var_activity_inc_decay before short incremental Solve (0: never stop; relevant only if /decision/vsids/var_activity_inc_decay_reinit_s=1)", 0 };
CTopiParam<uint32_t> m_ParamVarActivityIncDecayStopReinitRestart = { m_Params, "/decision/vsids/var_activity_inc_decay_stop_reinit_restart", "The first restart to stop re-initializing /decision/vsids/var_activity_inc_decay before short incremental Solve (0: never stop; relevant only if /decision/vsids/var_activity_inc_decay_reinit_s=1)", 0 };
CTopiParam<uint32_t> m_ParamVarActivityIncDecayStopReinitConflict = { m_Params, "/decision/vsids/var_activity_inc_decay_stop_reinit_conflict", "The first conflict to stop re-initializing /decision/vsids/var_activity_inc_decay before short incremental Solve (0: never stop; relevant only if /decision/vsids/var_activity_inc_decay_reinit_s=1)", 0 };
CTopiParam<double> m_ParamVarActivityIncDecayStopReinitTime = { m_Params, "/decision/vsids/var_activity_inc_decay_stop_reinit_time", "The time in sec. to stop re-initializing /decision/vsids/var_activity_inc_decay before short incremental Solve (0.0: never stop; relevant only if /decision/vsids/var_activity_inc_decay_reinit_s=1)", 0.0 };
CTopiParam<double> m_ParamVarActivityIncDecayReinitVal = { m_Params, "/decision/vsids/var_activity_inc_decay_reinit_val", "For /decision/vsids/var_activity_inc_decay_reinit_each_solve=1: the value to re-initialize /decision/vsids/var_activity_inc_decay before each Solve", {0.8, 0.8, 0.8, 0.8, 0.8, 0.925, 0.8, 0.8, 0.8}, numeric_limits<double>::epsilon(), 1.0 };
CTopiParam<double> m_ParamVarDecayInc = { m_Params, "/decision/vsids/var_decay_inc", "The increment value for var_activity_inc_decay each var_decay_update_conf_rate conflicts: m_ParamVarDecay += m_ParamVarDecayInc (hard-coded to 0.01 in Glucose-based solvers)", {0.01, 0.01, 0.01, 0.01, 0.01, 0.04, 0.01, 0.01, 0.01}, 0, 1.0 };
CTopiParam<double> m_ParamVarDecayIncAi = { m_Params, "/decision/vsids/var_decay_inc_ai", "After initial: the increment value for var_activity_inc_decay each var_decay_update_conf_rate conflicts: m_ParamVarDecay += m_ParamVarDecayInc (hard-coded to 0.01 in Glucose-based solvers)", 0.01, 0, 1.0 };
CTopiParam<double> m_ParamVarDecayIncS = { m_Params, "/decision/vsids/var_decay_inc_s", "Short incremental: The increment value for var_activity_inc_decay each var_decay_update_conf_rate conflicts: m_ParamVarDecay += m_ParamVarDecayInc (hard-coded to 0.01 in Glucose-based solvers)", {0.01, 0.01, 0.01, 0.01, 0.01, 0.0025, 0.01, 0.01, 0.01}, 0, 1.0 };
CTopiParam<double> m_ParamVarDecayMax = { m_Params, "/decision/vsids/var_decay_max", "The maximal value for var_activity_inc_decay", {0.99, 0.95, 0.9, 0.95, 0.95, 0.98, 0.95, 0.99, 0.9}, numeric_limits<double>::epsilon(), 1.0 };
CTopiParam<double> m_ParamVarDecayMaxAi = { m_Params, "/decision/vsids/var_decay_max_ai", "After initial: The maximal value for var_activity_inc_decay", {0.99, 0.95, 0.9, 0.95, 0.95, 0.99, 0.95, 0.99, 0.94}, numeric_limits<double>::epsilon(), 1.0 };
CTopiParam<double> m_ParamVarDecayMaxS = { m_Params, "/decision/vsids/var_decay_max_s", "Short incremental: The maximal value for var_activity_inc_decay", {0.99, 0.95, 0.9, 0.95, 0.95, 0.98, 0.95, 0.99, 0.94}, numeric_limits<double>::epsilon(), 1.0 };
CTopiParam<uint32_t> m_ParamVarDecayUpdateConfRate = { m_Params, "/decision/vsids/var_decay_update_conf_rate", "The rate in conflicts of var_decay's update (5000 in Glucose-based solvers)", 5000, 1 };
inline bool IsVsidsInitOrderParam(const string& paramName) const { return paramName == "/decision/vsids/init_order"; }
CTopiParam<bool> m_ParamVsidsInitOrder = { m_Params, "/decision/vsids/init_order", "The order of inserting into the VSIDS heap (0: bigger indices first; 1: smaller indices first)", {false, true, false, true, true, false, true, false, false} };
CTopiParam<bool> m_ParamVsidsInitOrderAi = { m_Params, "/decision/vsids/init_order_ai", "After initial call: the order of inserting into the VSIDS heap (0: bigger indices first; 1: smaller indices first)", {false, true, false, true, true, false, true, true, false} };
CTopiParam<bool> m_ParamVarActivityGlueUpdate = { m_Params, "/decision/vsids/var_activity_glue_update", "Do we increase the VSIDS score for every last-level variable, visited during a conflict, whose parent is a learnt clause with LBD score lower than that of the newly learnt clause?", {true, true, true, false, true, true, false, false, true} };
CTopiParam<bool> m_ParamVarActivityUseMapleLevelBreaker = { m_Params, "/decision/vsids/var_activity_use_maple_level_breaker", "Maple (MapleLCMDistChronoBT-f2trc-s) multiplies the variable activity bumping factor by 1.5 for variables, whose dec. level is higher-than-or-equal than 2nd highest-1 and by 0.5 for other variables; use it?", {false, false, false, true, true, false, true, false, false} };
CTopiParam<bool> m_ParamVarActivityUseMapleLevelBreakerAi = { m_Params, "/decision/vsids/var_activity_use_maple_level_breaker_ai", "After initial call: Maple (MapleLCMDistChronoBT-f2trc-s) multiplies the variable activity bumping factor by 1.5 for variables, whose dec. level is higher-than-or-equal than 2nd highest-1 and by 0.5 for other variables; use it?", {false, false, false, true, true, false, false, false, false} };
CTopiParam<uint32_t> m_ParamVarActivityMapleLevelBreakerDecrease = { m_Params, "/decision/vsids/var_activity_maple_level_breaker_decrease", "If var_activity_use_maple_level_breaker is on, this number is the decrease in the 2nd highest level, so that if the variable is higher-than-or-equal, its bump is more significant", {1, 1, 1, 1, 0, 1, 1, 1, 1} };
CTopiParam<uint8_t> m_ParamInitClssBoostScoreStrat = { m_Params, "/decision/init_clss_boost/strat", "Initial query: variable score boost strategy for user clauses -- 0: none; 1: no clause-size, user-order; 2: clause-size-aware, user-order; 3: no clause-size, reverse-user-order; 4: clause-size-aware, reverse-user-order", {2, 0, 0, 0, 0, 0, 4, 2, 0}, 0, 4 };
CTopiParam<uint8_t> m_ParamInitClssBoostScoreStratAfterInit = { m_Params, "/decision/init_clss_boost/strat_after_init", "After initial query: variable score boost strategy for user clauses -- 0: none; 1: no clause-size, user-order; 2: clause-size-aware, user-order; 3: no clause-size, reverse-user-order; 4: clause-size-aware, reverse-user-order", {1, 0, 0, 0, 0, 4, 0, 1, 0}, 0, 4 };
CTopiParam<double> m_ParamInitClssBoostMultHighest = { m_Params, "/decision/init_clss_boost/mult_highest", "Variable score boost for initial clauses: highest mult value", {10., 10., 10., 10., 10., 10., 10., 5., 10.} };
CTopiParam<double> m_ParamInitClssBoostMultLowest = { m_Params, "/decision/init_clss_boost/mult_lowest", "Variable score boost for initial clauses: lowest mult value", 1. };
CTopiParam<double> m_ParamInitClssBoostMultDelta = { m_Params, "/decision/init_clss_boost/mult_delta", "Variable score boost for initial clauses: delta mult value", {0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.01, 0.0001} };
CTopiParam<bool> m_ParamRandomizePolarityAtEachIncrementalCall = { m_Params, "/decision/polarity/randomize_at_incremental_calls", "Randomize the polarities of all the variables once at the beginning of each incremental call", false };
// Parameters: backtracking
CTopiParam<TUV> m_ParamChronoBtIfHigherInit = { m_Params, "/backtracking/chrono_bt_if_higher_init", "Initial query: backtrack chronologically, if the decision level difference is higher than the parameter", {100, numeric_limits<TUV>::max(), 50, 100, 100, 50, 100, 0, 100} };
CTopiParam<TUV> m_ParamChronoBtIfHigherN = { m_Params, "/backtracking/chrono_bt_if_higher_n", "Normal (non-short) incremental query: Backtrack chronologically, if the decision level difference is higher than the parameter", {100, numeric_limits<TUV>::max(), 50, 100, 100, 50, 100, 0, 50} };
CTopiParam<TUV> m_ParamChronoBtIfHigherS = { m_Params, "/backtracking/chrono_bt_if_higher_s", "Short incremental query: Backtrack chronologically, if the decision level difference is higher than the parameter", {100, numeric_limits<TUV>::max(), 50, 100, 100, 50, 100, 100, 50} };
CTopiParam<uint32_t> m_ParamConflictsToPostponeChrono = { m_Params, "/backtracking/conflicts_to_postpone_chrono", "The number of conflicts to postpone considering any backtracking, but NCB", {0, 0, 0, 4000, 8000, 0, 4000, 0, 4000} };
CTopiParam<uint8_t> m_ParamCustomBtStratInit = { m_Params, "/backtracking/custom_bt_strat_init", "Initial query: 0: no custom backtracking; 1, 2: backtrack to the level containing the variable with the best score *instead of any instances of supposed chronological backtracking*, where ties are broken based on the value -- 1: higher levels are preferred; 2: lower levels are preferred ", {2, 0, 0, 0, 1, 0, 0, 0, 0}, 0, 2 };
CTopiParam<uint8_t> m_ParamCustomBtStratN = { m_Params, "/backtracking/custom_bt_strat_n", "Normal (non-short) incremental query: 0: no custom backtracking; 1, 2: backtrack to the level containing the variable with the best score *instead of any instances of supposed chronological backtracking*, where ties are broken based on the value -- 1: higher levels are preferred; 2: lower levels are preferred ", {0, 0, 0, 0, 1, 0, 0, 0, 0}, 0, 2 };
CTopiParam<uint8_t> m_ParamCustomBtStratS = { m_Params, "/backtracking/custom_bt_strat_s", "Short incremental query: 0: no custom backtracking; 1, 2: backtrack to the level containing the variable with the best score *instead of any instances of supposed chronological backtracking*, where ties are broken based on the value -- 1: higher levels are preferred; 2: lower levels are preferred ", {2, 0, 0, 0, 1, 0, 0, 0, 0}, 0, 2 };
CTopiParam<bool> m_ParamReuseTrail = { m_Params, "/backtracking/reuse_trail", "0: no trail re-usage; 1: re-use trail (the idea is from SAT'20 Hickey&Bacchus' paper, but our implementation is fully compatible with CB)", 0 };
// Parameters: BCP
constexpr uint8_t InitEntriesPerWL() { return 4 >= TWatchInfo::BinsInLongBitCeil ? 4 : TWatchInfo::BinsInLongBitCeil; };
CTopiParam<uint8_t> m_ParamInitEntriesPerWL = { m_Params, "/bcp/init_entries_per_wl", "BCP: the number of initial entries in a watch list", InitEntriesPerWL(), TWatchInfo::BinsInLongBitCeil };
CTopiParam<uint8_t> m_ParamBCPWLChoice = { m_Params, "/bcp/wl_choice", "User clause processing: how to choose the watches -- 0: prefer shorter WL; 1: prefer longer WL; 2: disregard WL length", {0, 2, 0, 1, 0, 0, 1, 0, 0}, 0, 2 };
CTopiParam<uint8_t> m_ParamExistingBinWLStrat = { m_Params, "/bcp/existing_bin_wl_start", "BCP: what to do about duplicate binary clauses -- 0: nothing; 1: boost their VSIDS score; 2: add another copy to the watches", {1, 1, 1, 1, 2, 1, 1, 1, 1}, 0, 2 };
CTopiParam<double> m_ParamBinWLScoreBoostFactor = { m_Params, "/bcp/bin_wl_start_score_boost_factor", "BCP: if /bcp/existing_bin_wl_start=1, what's the factor for boosting the scores", {1., 1., 1., 1., 1., 1., 1., 0.5, 1.}, numeric_limits<double>::epsilon() };
CTopiParam<uint8_t> m_ParamBestContradictionStrat = { m_Params, "/bcp/best_contradiction_strat", "BCP's best contradiction strategy: 0: size; 1: glue; 2: first; 3: last", {0, 0, 0, 0, 0, 0, 0, 3, 0}, 0, 3 };
// Parameters: Add-user-clause
CTopiParam<uint32_t> m_ParamAddClsRemoveClssGloballySatByLitMinSize = { m_Params, "/add_user_clause/remove_clss_globally_sat_by_literal_larger_size", "Assigned literal strategy: check for literals satisfied at decision level 0 and remove globally satisfied clauses for sizes larger than this parameter", {numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), 2, numeric_limits<uint32_t>::max()} };
CTopiParam<uint32_t> m_ParamAddClsRemoveClssGloballySatByLitMinSizeAi = { m_Params, "/add_user_clause/remove_clss_globally_sat_by_literal_larger_size_ai", "After initial call: assigned literal strategy: check for literals satisfied at decision level 0 and remove globally satisfied clauses for sizes larger than this parameter", {numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), 5, numeric_limits<uint32_t>::max()} };
CTopiParam<bool> m_ParamAddClsAtLevel0 = { m_Params, "/add_user_clause/guarantee_level_0", "Guarantee that adding a user clause always occurs at level 0 (by backtracking to 0 after every solve)", false };
// Parameters: Query type
CTopiParam<uint32_t> m_ParamShortQueryConfThrInv = { m_Params, "/query_type/short_query_conf_thr", "If the conflict threshold is at most this parameter, this invocation is considered to be incremental short", 10000 };
// Parameters: debugging
CTopiParam<uint8_t> m_ParamAssertConsistency = { m_Params, "/debugging/assert_consistency", "Debugging only: assert the consistency (0: none; 1: trail; 2: trail and WL's for assigned; 3: trail and WL's for all -- an extremely heavy operation)", 0, 0, 3 };
CTopiParam<uint32_t> m_ParamAssertConsistencyStartConf = { m_Params, "/debugging/assert_consistency_start_conf", "Debugging only; meaningful only if /debugging/assert_consistency=1: assert the consistency starting with the provided conflicts number", 0 };
CTopiParam<uint32_t> m_ParamPrintDebugModelInvocation = { m_Params, "/debugging/print_debug_model_invocation", "The number of solver invocation to print the model in debug-model format: intended to be used for internal Topor debugging", 0 };
CTopiParam<uint32_t> m_ParamVerifyDebugModelInvocation = { m_Params, "/debugging/verify_debug_model_invocation", "The number of solver invocation, when the debug-model is verified: intended to be used for internal Topor debugging", 0 };
// Parameters: assumptions handling
CTopiParam<bool> m_ParamAssumpsSimpAllowReorder = { m_Params, "/assumptions/allow_reorder", "Assumptions handling: allow reordering assumptions when filtering", true };
CTopiParam<bool> m_ParamAssumpsIgnoreInGlue = { m_Params, "/assumptions/ignore_in_glue", "Assumptions handling: ignore assumptions when calculating the glue score (following the SAT'13 paper \"Improving Glucose for Incremental SAT Solving with Assumptions : Application to MUS Extraction\")", false };
// Parameters: conflict analysis
CTopiParam<bool> m_ParamMinimizeClausesMinisat = { m_Params, "/conflicts/minimize_clauses", "Conflict analysis: apply deep conflict clause minimization", true };
CTopiParam<uint32_t> m_ParamMinimizeClausesBinMaxSize = { m_Params, "/conflicts/bin_res_max_size", "Conflict analysis: maximal size to apply binary minimization (both this condition and maximal LBD must hold; 30 in Glucose, Fiver, Maple)", {30, 30, 30, 30, 50, 30, 30, 30, 30} };
CTopiParam<uint32_t> m_ParamMinimizeClausesBinMaxLbd = { m_Params, "/conflicts/bin_res_max_lbd", "Conflict analysis: maximal LBD to apply binary minimization (both this condition and maximal size must hold; 6 in Glucose, Fiver, Maple)", 6 };
CTopiParam<uint32_t> m_ParamFlippedRecordingMaxLbdToRecord = { m_Params, "/conflicts/flipped_recording_max_lbd", "Conflict analysis: record a flipped clause with LBD smaller than or equal to the value of the parameter", {numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), 0, 40, numeric_limits<uint32_t>::max(), 0, 90, numeric_limits<uint32_t>::max()} };
CTopiParam<bool> m_ParamFlippedRecordDropIfSubsumed = { m_Params, "/conflicts/flipped_drop_if_subsumed", "Conflict analysis: test and drop the flipped clause, if subsumed by the main clause", true };
CTopiParam<uint32_t> m_ParamOnTheFlySubsumptionContradictingMinGlueToDisable = { m_Params, "/conflicts/on_the_fly_subsumption/contradicting_min_glue_to_disable", "Conflict analysis: the minimal glue (LBD) to disable on-the-fly subsumption during conflict analysis over the contradicting clause (1: apply only over initial clauses)", {8, 0, 0, 0, 0, 8, 0, 8, 0} };
CTopiParam<uint32_t> m_ParamOnTheFlySubsumptionParentMinGlueToDisable = { m_Params, "/conflicts/on_the_fly_subsumption/parent_min_glue_to_disable", "Conflict analysis: the minimal glue (LBD) to disable on-the-fly subsumption during conflict analysis over the parents (1: apply only over initial clauses)", {30, 0, 0, 0, 0, 1, 0, 30, 16} };
CTopiParam<uint32_t> m_ParamOnTheFlySubsumptionContradictingFirstRestart = { m_Params, "/conflicts/on_the_fly_subsumption/contradicting_first_restart", "Conflict analysis: the first restart after which on-the-fly subsumption over the contradicting clause is enabled", 1 };
CTopiParam<uint32_t> m_ParamOnTheFlySubsumptionParentFirstRestart = { m_Params, "/conflicts/on_the_fly_subsumption/parent_first_restart", "Conflict analysis: the first restart after which on-the-fly subsumption over the parent clause is enabled", 1 };
CTopiParam<uint8_t> m_ParamAllUipMode = { m_Params, "/conflicts/all_uip/mode", "Conflict analysis: ALL-UIP scheme mode -- 0: disabled; 1: only main clause; 2: only flipped clause; 3: both main and flipped", 0, 0, 3 };
CTopiParam<uint32_t> m_ParamAllUipFirstRestart = { m_Params, "/conflicts/all_uip/first_restart", "Conflict analysis: the first restart after which the ALL-UIP scheme is enabled", 0 };
CTopiParam<uint32_t> m_ParamAllUipLastRestart = { m_Params, "/conflicts/all_uip/last_restart", "Conflict analysis: the last restart after which the ALL-UIP scheme is enabled", numeric_limits<uint32_t>::max() };
CTopiParam<double> m_ParamAllUipFailureThr = { m_Params, "/conflicts/all_uip/success_rate_failure_thr", "Conflict analysis: the threshold on ALL-UIP scheme failure (0.8 in the SAT'20 paper)", 0.8 };
// Parameters: restart strategy
static constexpr uint8_t RESTART_STRAT_NUMERIC = 0;
static constexpr uint8_t RESTART_STRAT_LBD = 1;
static constexpr uint8_t RESTART_STRAT_NONE = 2;
// Restart strategy: initial query
CTopiParam<uint8_t> m_ParamRestartStrategyInit = { m_Params, "/restarts/strategy_init", "Restart strategy for the initial query: 0: numeric (arithmetic, luby or in/out); 1: LBD-average-based", {RESTART_STRAT_NUMERIC, RESTART_STRAT_LBD, RESTART_STRAT_NUMERIC, RESTART_STRAT_LBD, RESTART_STRAT_LBD, RESTART_STRAT_LBD, RESTART_STRAT_LBD, RESTART_STRAT_NUMERIC, RESTART_STRAT_NUMERIC}, 0, 1 };
// Restart strategy: normal incremental query
CTopiParam<uint8_t> m_ParamRestartStrategyN = { m_Params, "/restarts/strategy_n", "Restart strategy for the normal (non-short) incremental query: 0: arithmetic; 1: LBD-average-based", {RESTART_STRAT_NUMERIC, RESTART_STRAT_LBD, RESTART_STRAT_NUMERIC, RESTART_STRAT_LBD, RESTART_STRAT_LBD, RESTART_STRAT_LBD, RESTART_STRAT_LBD, RESTART_STRAT_NUMERIC, RESTART_STRAT_NUMERIC}, 0, 1 };
// Restart strategy: short incremental query
CTopiParam<uint8_t> m_ParamRestartStrategyS = { m_Params, "/restarts/strategy_s", "Restart strategy for the short incremental query: 0: arithmetic; 1: LBD-average-based", {RESTART_STRAT_NUMERIC, RESTART_STRAT_LBD, RESTART_STRAT_NUMERIC, RESTART_STRAT_LBD, RESTART_STRAT_LBD, RESTART_STRAT_LBD, RESTART_STRAT_LBD, RESTART_STRAT_NUMERIC, RESTART_STRAT_NUMERIC}, 0, 1 };
CTopiParam<bool> m_ParamRestartNumericLocal = { m_Params, "/restarts/numeric/is_local", "Restarts, numeric strategies: use local restarts?", true };
CTopiParam<uint32_t> m_ParamRestartNumericInitConfThr = { m_Params, "/restarts/numeric/conflict_thr", "Restarts, numeric strategy: the initial value for the conflict threshold, which triggers a restart", {1000, 1000, 1000, 1000, 100, 1000, 1000, 1000, 1000}, 1 };
CTopiParam<uint8_t> m_ParamRestartNumericSubStrat = { m_Params, "/restarts/numeric/sub_strat", "Restarts, numeric sub-strategy: 0: arithmetic; 1: luby", 0, 0, 1 };
CTopiParam<uint32_t> m_ParamRestartArithmeticConfIncr = { m_Params, "/restarts/arithmetic/conflict_increment", "Restarts, arithmetic numeric strategy: increment value for conflicts", {0, 50, 50, 50, 100, 0, 50, 1, 50} };
CTopiParam<double> m_ParamRestartLubyConfIncr = { m_Params, "/restarts/luby/conflict_increment", "Restarts, luby numeric strategy: increment value for conflicts", {1.5, 1.5, 1.5, 2, 1.5, 1.5, 2, 1.5, 1.5}, 1 + numeric_limits<double>::epsilon() };
CTopiParam<uint32_t> m_ParamRestartLbdWinSize = { m_Params, "/restarts/lbd/win_size", "Restart, LBD-average-based strategy: window size", {50, 50, 50, 50, 25, 50, 50, 50, 50}, 1 };
CTopiParam<uint32_t> m_ParamRestartLbdThresholdGlueVal = { m_Params, "/restarts/lbd/thr_glue_val", "Restart, LBD-average-based strategy: the maximal value for LBD queue update", {numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max(), 50, 50, numeric_limits<uint32_t>::max(), 50, numeric_limits<uint32_t>::max(), numeric_limits<uint32_t>::max()} };
CTopiParam<double> m_ParamRestartLbdAvrgMult = { m_Params, "/restarts/lbd/average_mult", "Restarts, LBD-average-based strategy: the multiplier in the formula for determining whether it's time to restart: recent-LBD-average * multiplier > global-LBD-average", {0.8, 0.8, 0.8, 0.8, 0.9, 0.8, 0.8, 0.8, 0.8} };
CTopiParam<bool> m_ParamRestartLbdBlockingEnable = { m_Params, "/restarts/lbd/blocking/enable", "Restarts, LBD-average-based blocking enable", {true, true, false, false, true, true, false, true, false} };
CTopiParam<uint32_t> m_ParamRestartLbdBlockingConfsToConsider = { m_Params, "/restarts/lbd/blocking/conflicts_to_consider_blocking", "Restarts, LBD-average-based blocking strategy: the number of conflicts to consider blocking; relevant, if /restarts/lbd/blocking/enable=1", {10000, 10000, 10000, numeric_limits<uint32_t>::max(), 10000, 10000, numeric_limits<uint32_t>::max(), 10000, 10000} };
CTopiParam<double> m_ParamRestartLbdBlockingAvrgMult = { m_Params, "/restarts/lbd/blocking/average_mult", "Restarts, LBD-average-based blocking strategy: the multiplier in the formula for determining whether the restart is blocked: #assignments > multiplier * assignments-average", 1.4 };
CTopiParam<uint32_t> m_ParamRestartLbdBlockingWinSize = { m_Params, "/restarts/lbd/blocking/win_size", "Restarts, LBD-average-based blocking strategy: window size", {5000, 5000, 5000, 5000, 5000, 10000, 5000, 5000, 5000}, 1 };
// Parameters: buffer multipliers
inline bool IsMultiplierParam(const string& paramName) const { return paramName == "/multiplier/clauses" || paramName == "/multiplier/variables" || paramName == "/multiplier/watches_if_separate"; }
CTopiParam<double> m_ParamMultClss = { m_Params, "/multiplier/clauses", "The multiplier for reallocating the clause buffer", CDynArray<TUV>::MultiplierDef, 1. };
CTopiParam<double> m_ParamMultVars = { m_Params, "/multiplier/variables", "The multiplier for reallocating data structures, indexed by variables (and literals)", 1., 1. };
CTopiParam<double> m_ParamMultWatches = { m_Params, "/multiplier/watches", "The multiplier for reallocating the watches buffer", 1.33, 1. };
CTopiParam<double> m_ParamMultWasteWatches = { m_Params, "/multiplier/watches_waste", "The multiplier for triggering reallocation of the watches buffer, when there is too much waste", 1.33, 1. };
// Parameters: clause simplification
CTopiParam<bool> m_ParamSimplify = { m_Params, "/deletion/simplify", "Simplify?", true };
CTopiParam<uint8_t> m_ParamSimplifyGlobalLevelScoreStrat = { m_Params, "/deletion/simplify_global_level_strat", "Simplify: how to update the score of the only remaining globally assigned variable (relevant only when /backtracking/custom_bt_strat != 0) -- 0: don't touch; 1: minimal out of all globals; 2: maximal out of all globals", 0, 0, 2 };
// Parameters: data-based compression
CTopiParam<double> m_ParamWastedFractionThrToDelete = { m_Params, "/deletion/wasted_fraction_thr", "If wasted > size * this_parameter, we physically compress the memory (0.2 in Fiver, Maple)", 0.2, numeric_limits<double>::epsilon(), 1. };
CTopiParam<bool> m_ParamCompressAllocatedPerWatch = { m_Params, "/deletion/compress_allocated_per_watch", "Tightly compress the allocated memory per every watch during memory compression (or, otherwise, never compress per watch)", true };
// Parameters: clause deletion
CTopiParam<uint8_t> m_ParamClsDelStrategy = { m_Params, "/deletion/clause/strategy", "Clause deletion strategy (0: no clause deletion; 1: Topor; 2: Fiver)", 1, 0, 2 };
CTopiParam<bool> m_ParamClsDelDeleteOnlyAssumpDecLevel = { m_Params, "/deletion/clause/delete_only_assump_dec_level", "Clause deletion: apply clause deletion only when at assumption decision level", false };
CTopiParam<double> m_ParamClsLowDelActivityDecay = { m_Params, "/deletion/clause/activity_decay", "Clause deletion: activity decay factor", 0.999, numeric_limits<double>::epsilon(), 1. };
CTopiParam<float> m_ParamClsDelLowFracToDelete = { m_Params, "/deletion/clause/frac_to_delete", "Clause deletion: the fraction of clauses to delete", {0.7f, 0.8f, 0.8f, 0.8f, 0.8f, 0.7f, 0.8f, 0.7f, 0.8f}, numeric_limits<float>::epsilon(), (float)1.f };
CTopiParam<uint32_t> m_ParamClsDelLowTriggerInit = { m_Params, "/deletion/clause/trigger_init", "Clause deletion: the initial number of learnts to trigger clause deletion", 6000 };
CTopiParam<uint32_t> m_ParamClsDelLowTriggerInc = { m_Params, "/deletion/clause/trigger_linc", "Clause deletion: the increment in learnts to trigger clause deletion", 75 };
CTopiParam<double> m_ParamClsDelS1LowTriggerMult = { m_Params, "/deletion/clause/s1/trigger_inc_mult", "Clause deletion: the change in increment in learnts to trigger clause deletion (that is, the value by which /deletion/clause/trigger_linc is multiplied)", 1.2, 1. };
CTopiParam<uint32_t> m_ParamClsDelS1LowTriggerMax = { m_Params, "/deletion/clause/s1/trigger_max", "Clause deletion: the maximal number of learnts to activate clause deletion", 60000 };
CTopiParam<uint8_t> m_ParamClsDelS2LowGlue = { m_Params, "/deletion/clause/s2/low_glue", "Clause deletion: the low glue for an additional current-change push", {3, 3, 3, 3, 3, 6, 3, 3, 3} };
CTopiParam<uint8_t> m_ParamClsDelS2MediumGlue = { m_Params, "/deletion/clause/s2/medium_glue", "Clause deletion: the medium glue for an additional current-change push", {5, 5, 5, 5, 5, 8, 5, 5, 5} };
CTopiParam<uint32_t> m_ParamClsDelS2LowMediumIncValue = { m_Params, "/deletion/clause/s2/low_medium_inc", "Clause deletion: the increment for the low&medium push to current-change", 1000 };
CTopiParam<TUV> m_ParamClsDelLowMinGlueFreeze = { m_Params, "/deletion/clause/glue_min_freeze", "Initial query: clause deletion: protect clauses for one round if their glue decreased and is lower than this value", {4, 30, 30, 30, 30, 5, 30, 30, 30}, 0, (TUV)numeric_limits<uint8_t>::max() };
CTopiParam<TUV> m_ParamClsDelLowMinGlueFreezeAi = { m_Params, "/deletion/clause/glue_min_freeze_ai", "Normal incremental query: clause deletion: protect clauses for one round if their glue decreased and is lower than this value", 30, 0, (TUV)numeric_limits<uint8_t>::max() };
CTopiParam<TUV> m_ParamClsDelLowMinGlueFreezeS = { m_Params, "/deletion/clause/glue_min_freeze_s", "Short incremental query: clause deletion: protect clauses for one round if their glue decreased and is lower than this value", {5, 30, 30, 30, 30, 5, 30, 30, 30}, 0, (TUV)numeric_limits<uint8_t>::max() };
CTopiParam<TUV> m_ParamClsDelGlueNeverDelete = { m_Params, "/deletion/clause/glue_never_delete", "Clause deletion: the highest glue value blocking clause deletion", {2, 2, 2, 2, 2, 3, 2, 2, 2}, 0, (TUV)numeric_limits<uint8_t>::max() };
CTopiParam<TUV> m_ParamClsDelGlueClusters = { m_Params, "/deletion/clause/glue_clusters", "Clause deletion: the number of glue clusters", {11, 0, 0, 0, 0, 11, 0, 8, 0}, 0, (TUV)numeric_limits<uint8_t>::max() };
CTopiParam<TUV> m_ParamClsDelGlueMaxCluster = { m_Params, "/deletion/clause/glue_max_lex_cluster", "Clause deletion: the highest glue which makes the clause belong to a glue-cluster", {16, 0, 0, 0, 0, 16, 0, 16, 3}, 0, (TUV)numeric_limits<uint8_t>::max() };
// Parameters: phase saving
CTopiParam<bool> m_ParamPhaseMngForceSolution = { m_Params, "/phase/force_solution", "Phase management: always force (the polarities of) the latest solution?", {false, false, false, false, false, false, true, false, false} };
CTopiParam<uint16_t> m_ParamPhaseMngRestartsBlockSize = { m_Params, "/phase/restarts_block_size", "Phase management: the number of restarts in a block for phase management considerations", 10, 1 };
CTopiParam<double> m_ParamPhaseMngUnforceRestartsFractionInit = { m_Params, "/phase/unforce_restarts_fraction_init", "Phase management for the initial query: don't force the polarities for the provided fraction of restarts", 0.25, 0., 1. };
CTopiParam<double> m_ParamPhaseMngUnforceRestartsFractionN = { m_Params, "/phase/unforce_restarts_fraction_n", "Phase management for the normal (non-short) incremental query: don't force the polarities for the provided fraction of restarts", 0., 0., 1. };
CTopiParam<double> m_ParamPhaseMngUnforceRestartsFractionS = { m_Params, "/phase/unforce_restarts_fraction_s", "Phase management for the short incremental query: don't force the polarities for the provided fraction of restarts", 0., 0., 1. };
CTopiParam<uint8_t> m_ParamPhaseMngStartInvStrat = { m_Params, "/phase/start_inv_strat", "Phase management: startegy to start an invocation with; relevant when 0 < /phase/unforce_restarts_fraction < 1: 0: start with force; 1: start with unforce; 2: start with rand", 0, 0, 2 };
CTopiParam<bool> m_ParamPhaseBoostFlippedForced = { m_Params, "/phase/boost_flipped_forced", "Phase management: boost the scores of forced variables, flipped by BCP?", false };
CTopiParam<uint8_t> m_ParamUpdateParamsWhenVarFixed = { m_Params, "/phase/update_params_when_var_fixed", "Phase management: update the parameters to pre-defined values, when fixed-only-once (1) or fixed-forever (2) or either (3)", {0, 0, 0, 0, 0, 0, 0, 0, 3}, 0, 3 };
/*
* INITIALIZATION-RELATED
*/
// The number of initially allocated entries in variable-indexed arrays
const size_t m_InitVarNumAlloc;
// The number of initially allocated entries in literal-indexed arrays
inline size_t GetInitLitNumAlloc() const;
// Handle a potentially new user variable
void HandleIncomingUserVar(TLit v, bool isUndoable = false);
/*
* STATUS
*/
bool m_IsSolveOngoing = false;
TToporStatus m_Status = TToporStatus::STATUS_UNDECIDED;
string m_StatusExplanation;
inline bool IsUnrecoverable() const { return m_Status >= TToporStatus::STATUS_FIRST_UNRECOVERABLE; }
inline bool IsErroneous() const { return m_Status >= TToporStatus::STATUS_FIRST_PERMANENT_ERROR; }
inline void SetStatus(TToporStatus s, string&& expl = "") { m_Status = s; m_StatusExplanation = move(expl); }
inline TToporReturnVal UnrecStatusToRetVal() const;
inline TToporReturnVal StatusToRetVal() const;
inline void SetOverallTimeoutIfAny();
/*
* INITIALIZATION AND EXTERNAL->INTERNAL VARIABLE MAP
*/
// external variable-->internal literal map
CDynArray<TULit> m_E2ILitMap;
CVector<TLit> m_NewExternalVarsAddUserCls;
// internal variable-->external literal map (initialized only, if required, e.g., for callbacks)
CDynArray<TLit> m_I2ELitMap;
inline TLit GetExternalLit(TULit iLit) { return IsNeg(iLit) ? -m_I2ELitMap[GetVar(iLit)] : m_I2ELitMap[GetVar(iLit)]; }
bool UseI2ELitMap() const { return m_ParamVerifyDebugModelInvocation != 0 || IsCbLearntOrDrat() || M_ReportUnitCls != nullptr; }
static constexpr TLit ExternalLit2ExternalVar(TLit l) { return l > 0 ? l : -l; }
inline TULit E2I(TLit l) const
{
const TLit externalV = ExternalLit2ExternalVar(l);
const TULit internalL = m_E2ILitMap[externalV];
return l < 0 ? Negate(internalL) : internalL;
}
// Used to make sure tautologies are discovered and duplicates are removed in new clauses
class CHandleNewCls;
CHandleNewCls m_HandleNewUserCls;
// The last internal variable so-far
TUVar m_LastExistingVar = 0;
inline TUVar GetNextVar() const { return m_LastExistingVar + 1; }
inline TULit GetLastExistingLit() const { return GetLit((TULit)m_LastExistingVar, true); }
inline TULit GetNextLit() const { return GetLastExistingLit() + 1; }
inline TULit GetAssignedLitForVar(TUVar v) const { assert(IsAssignedVar(v)); return GetLit(v, m_AssignmentInfo[v].m_IsNegated); }
/*
* CLAUSE-BUFFER
*/
// BIT-COMPRESSED BUFFERS
// The minimal clause size
static constexpr uint8_t BCMinClsSize = 3;
// The structure of an index into the bit-compressed buffers
// 1 bit: is learnt clause
constexpr static size_t BitsForLearnt = 1;
// 5 bits: bits for [clause size]
// hence, maximal clause size for M=3: N^max = 2^{S+1}+M-2 = 2^{31+1}+3-2 = 4,294,967,297, since S=2^5-1=31 for 5 bits here
constexpr static size_t BitsForClsSize = 5;
// 5 (if literal is 32-bit) bits: bits for each literal
// hence, the maximal literal is 2^(2^5=32) = 4,294,967,296
constexpr static size_t BitsForLit = bit_width((size_t)numeric_limits<TULit>::digits - 1);
static_assert((size_t)numeric_limits<TULit>::digits != 32 || BitsForLit == 5);
// [is-learnt:1][size bits:5][max literal width:5]
constexpr static size_t BitsForHashId = BitsForLearnt + BitsForClsSize + BitsForLit;
// Buffer structure:
// Initial clause layout in the buffer with the widths
// [size: m_BitsForClsSize] [l1: BitsForLit] [l2: BitsForLit] ... [ln: BitsForLit]
// Deleted clause: [size: m_BitsForClsSize] [0: BitsForLit] [optional-binlit1: BitsForLit] [optional-binlit2: BitsForLit] ... [ln: BitsForLit]
// Conflict clause layout in the buffer:
// [size: m_BitsForClsSize] [glue: min(11, m_BitsForClsSize+2)] [stay-for-another-round: 1] [activity: 31] [l1: BitsForLit] [l2: BitsForLit] ... [ln: BitsForLit]
// Deleted clause: [size: m_BitsForClsSize] [glue: min(11, m_BitsForClsSize+2)] [stay-for-another-round: 1] [0: BitsForLit] [optional-binlit1: BitsForLit] [optional-binlit2: BitsForLit] ... [ln: BitsForLit]
// Deleted literal in any buffer: [0: BitsForLit]. Works, since:
// (1) There can be no deleted literals for clauses of size 3, whose number of bits for clause size is 0 (since binary clauses are stored separately)
// (2) the number of bits for a literal is never lower than for the clause size
struct TBCHashId
{
TBCHashId() { assert(IsError()); }
TBCHashId(uint16_t v) : m_Val(v) {}
TBCHashId(bool isLearnt, uint16_t bitsForClsSize, uint16_t bitsForLit) : m_IsLearnt(isLearnt), m_BitsForClsSize(bitsForClsSize), m_BitsForLit(bitsForLit), m_BitsRest(0)
{
assert(m_BitsForClsSize <= m_BitsForLit);
}
union
{
struct
{
uint16_t m_IsLearnt : BitsForLearnt;
uint16_t m_BitsForClsSize : BitsForClsSize;
uint16_t m_BitsForLit : BitsForLit;
uint16_t m_BitsRest : sizeof(uint16_t) * 8 - BitsForLearnt - BitsForClsSize - BitsForLit;
};
uint16_t m_Val = 0;
};
static constexpr uint8_t BCHashIdBits() { return BitsForHashId; }
inline operator uint16_t() const { return m_Val; }
inline bool IsError() const { return m_BitsForLit == 0; }
inline void SetError() { m_BitsForLit = 0; }
inline uint8_t GetBitsGlue() const { return (size_t)m_BitsForClsSize + 2 < BitsForHashId ? (uint8_t)m_BitsForClsSize + 2 : (uint8_t)BitsForHashId; }
inline uint8_t GetFirstLitOffset() const { return m_BitsForClsSize + m_IsLearnt * (GetBitsGlue() + GetBitsActivityAndSkipDel()); }
inline TUV MaxGlue() const { return ((TUV)1 << GetBitsGlue()) - 1; }
constexpr static uint8_t GetBitsSkipDel() { return 1; }
constexpr static uint8_t GetBitsActivity() { return 31; }
constexpr static uint8_t GetBitsActivityAndSkipDel() { return GetBitsActivity() + GetBitsSkipDel(); }
};
static_assert(sizeof(TBCHashId) == sizeof(uint16_t));
// Clause-sizes: bits-for-clause-size
// 3: 0 (special value not needed, since literals are not deleted for clauses of size 3; otherwise, special value 0 means that this is not a clause, but a deleted literal)
// 4: 1 (0 -- special, 1)
// 5-7: 2 (0 -- special, 1-3)
// 8-14: 3 (0 -- special, 1-7)
// 15-29: 4 (0 -- special, 1-15)
// 30-60: 5 (0 -- special, 1-31)
// 61-123: 6 (0 -- special, 1-63)
// 124-250: 7 (0 -- special, 1-127)
// 251-505: 8 (0 -- special, 1-255)
// 506-1016: 9 (0 -- special, 1-511)
// ...
// stored in lowestClsSizePerBits outside of the class, since there was a problem to declare a constexpr array inside of a templated class,
// where the function for low bound is 2^n - n + 3
void LowestClsSizePerBitsStaticAsserts()
{
static_assert(lowestClsSizePerBits[0] == 3);
static_assert(lowestClsSizePerBits[1] == 4);
static_assert(lowestClsSizePerBits[2] == 5);
static_assert(lowestClsSizePerBits[3] == 8);
static_assert(lowestClsSizePerBits[4] == 15);
static_assert(lowestClsSizePerBits[5] == 30);
static_assert(lowestClsSizePerBits[6] == 61);
static_assert(lowestClsSizePerBits[7] == 124);
static_assert(lowestClsSizePerBits[8] == 251);
static_assert(lowestClsSizePerBits[9] == 506);
}
template <class T> static constexpr uint16_t BCClsSize2Bits(T clsSize)
{
assert(clsSize >= BCMinClsSize);
assert((uint64_t)clsSize <= (uint64_t)numeric_limits<uint32_t>::max());
const auto itFirstGreater = upper_bound(lowestClsSizePerBits.begin(), lowestClsSizePerBits.end(), ((uint32_t)clsSize));
return (uint16_t)(itFirstGreater - lowestClsSizePerBits.begin()) - 1;
}
template <class T> static constexpr uint32_t BCClsSize2EncodedClsSize(T clsSize)
{
assert(clsSize >= BCMinClsSize);
assert((uint64_t)clsSize <= (uint64_t)numeric_limits<uint32_t>::max());
return clsSize == BCMinClsSize ? 0 : (uint32_t)clsSize - lowestClsSizePerBits[BCClsSize2Bits(clsSize)] + 1;
}
// Encoded clause size + bits --> clause size
static constexpr uint32_t BCEncodedClsSize2ClsSizeConst(uint32_t encodedClsSize, uint16_t bitsForClsSize)
{
if (bitsForClsSize == 0)
{
return BCMinClsSize;
}
assert(encodedClsSize > 0);
return encodedClsSize + lowestClsSizePerBits[bitsForClsSize] - 1;
}
template <class TGetEncodedClsSize>
static constexpr uint32_t BCEncodedClsSize2ClsSize(TGetEncodedClsSize GetEncodedClsSize, uint16_t bitsForClsSize)
{
if (bitsForClsSize == 0)
{
return BCMinClsSize;
}
const auto encodedClsSize = (uint32_t)GetEncodedClsSize();
assert(encodedClsSize > 0);
return encodedClsSize + lowestClsSizePerBits[bitsForClsSize] - 1;
}
void BCClsSizeStaticAsserts()
{
static_assert(BCClsSize2Bits(3u) == 0);
static_assert(BCClsSize2Bits(4u) == 1);
static_assert(BCClsSize2Bits(5u) == 2);
static_assert(BCClsSize2Bits(6u) == 2);
static_assert(BCClsSize2Bits(7u) == 2);
static_assert(BCClsSize2Bits(8u) == 3);
static_assert(BCClsSize2Bits(9u) == 3);
static_assert(BCClsSize2Bits(14u) == 3);
static_assert(BCClsSize2Bits(15u) == 4);
static_assert(BCClsSize2Bits(16u) == 4);
static_assert(BCClsSize2Bits(29u) == 4);
static_assert(BCClsSize2Bits(30u) == 5);
static_assert(BCClsSize2Bits(31u) == 5);
static_assert(BCClsSize2EncodedClsSize(3u) == 0);
static_assert(BCClsSize2EncodedClsSize(4u) == 1);
static_assert(BCClsSize2EncodedClsSize(5u) == 1);
static_assert(BCClsSize2EncodedClsSize(6u) == 2);
static_assert(BCClsSize2EncodedClsSize(7u) == 3);
static_assert(BCClsSize2EncodedClsSize(8u) == 1);
static_assert(BCClsSize2EncodedClsSize(9u) == 2);
static_assert(BCClsSize2EncodedClsSize(14u) == 7);
static_assert(BCClsSize2EncodedClsSize(15u) == 1);
static_assert(BCEncodedClsSize2ClsSizeConst(0u, 0) == 3);
static_assert(BCEncodedClsSize2ClsSizeConst(1u, 1) == 4);
static_assert(BCEncodedClsSize2ClsSizeConst(1u, 2) == 5);
static_assert(BCEncodedClsSize2ClsSizeConst(2u, 2) == 6);
static_assert(BCEncodedClsSize2ClsSizeConst(3u, 2) == 7);
static_assert(BCEncodedClsSize2ClsSizeConst(1u, 3) == 8);
static_assert(BCEncodedClsSize2ClsSizeConst(2u, 3) == 9);
static_assert(BCEncodedClsSize2ClsSizeConst(7u, 3) == 14);
static_assert(BCEncodedClsSize2ClsSizeConst(1u, 4) == 15);
static_assert(BCEncodedClsSize2ClsSizeConst(2u, 4) == 16);
static_assert(BCEncodedClsSize2ClsSizeConst(15u, 4) == 29);
static_assert(BCEncodedClsSize2ClsSizeConst(1u, 5) == 30);
static_assert(BCEncodedClsSize2ClsSizeConst(2u, 5) == 31);
}
// Bits in the parent, remaining for the index into the clause bit-array, after counting hash-index's BitsForHashId bits
constexpr static size_t BitsForBCParentClsInd = sizeof(TUInd) * 8 - BitsForHashId;
// TUInd for the compressed buffer (used, e.g., for parents). Must have the same size as TUInd.
struct TBCInd
{
TBCInd(TUInd val = BadClsInd) : m_Val(val) {}
TBCInd(const TBCHashId bcHashId, uint64_t bitStart) :
m_IsLearnt(bcHashId.m_BitsForLit == 0 || bitStart > m_MaxBitStart ? false : bcHashId.m_IsLearnt),
m_BitsForClsSize(bcHashId.m_BitsForLit == 0 || bitStart > m_MaxBitStart ? 0 : bcHashId.m_BitsForClsSize),
m_BitsForLit(bcHashId.m_BitsForLit == 0 || bitStart > m_MaxBitStart ? 0 : bcHashId.m_BitsForLit),
m_BitStart(bcHashId.m_BitsForLit == 0 || bitStart > m_MaxBitStart ? 0 : (TUInd)bitStart)
{
assert(m_BitsForClsSize <= m_BitsForLit);
}
inline bool IsError() const { return m_Val == BadClsInd; }
inline operator TUInd() const { return m_Val; }
inline TBCHashId GetHashId() const { return TBCHashId(m_IsLearnt, m_BitsForClsSize, m_BitsForLit); }
inline TUInd BitFirstLit() const { return m_BitStart + TBCHashId(m_IsLearnt, m_BitsForClsSize, m_BitsForLit).GetFirstLitOffset(); }
inline uint8_t GetBitsGlue() const { return TBCHashId(m_IsLearnt, m_BitsForClsSize, m_BitsForLit).GetBitsGlue(); }
union
{
struct
{
TUInd m_IsLearnt : BitsForLearnt;
TUInd m_BitsForClsSize : BitsForClsSize;
TUInd m_BitsForLit : BitsForLit;
TUInd m_BitStart : BitsForBCParentClsInd;
};
TUInd m_Val = BadClsInd;
};
constexpr static uint64_t m_MaxBitStart = ((uint64_t)1 << (uint64_t)BitsForBCParentClsInd) - 1;
};
static_assert(sizeof(TBCInd) == sizeof(TUInd));
// Bit-compressed buffers, indexed by TBCHashId
unordered_map<uint16_t, CBitArray> m_BC;
// This is to used in order not to invalidate iterators in SimplifyIfRequired
unordered_map<uint16_t, CBitArray> m_BCSpare;
size_t BCNextBitSum() const;
size_t BCCapacitySum() const;
void BCRemoveGarbage(function<void(uint64_t oldInd, uint64_t newInd)> NotifyAboutRemainingChunkMove = nullptr)
{
assert(NV(2) || P("BCRemoveGarbage\n"));
TUInd toInd(0);
for (auto bcIt = m_BC.begin(); bcIt != m_BC.end(); toInd == 0 ? bcIt = m_BC.erase(bcIt) : ++bcIt)
{
TBCHashId bcHashInd = bcIt->first;
CBitArray& ba = bcIt->second;
TUInd fromInd(0);
toInd = 0;
while (fromInd < ba.bit_get_next_bit())
{
// Update fromInd to the next remaining clause (or to beyond the buffer capacity)
for (TBCInd bcInd(bcHashInd, fromInd); fromInd < ba.bit_get_next_bit() &&
((bcHashInd.m_BitsForClsSize != 0 && ba.bit_get(fromInd, bcHashInd.m_BitsForClsSize) == 0) ||
ba.bit_get(bcInd.BitFirstLit(), bcHashInd.m_BitsForLit) == 0);
bcInd = TBCInd(bcHashInd, fromInd))
{
fromInd = ClsEnd(bcInd);
}
if (fromInd >= ba.bit_get_next_bit())
{
// Nothing useful to move --> we're done!
break;
}
// Copy the current clause (starting at fromInd)
const TBCInd bcInd(bcHashInd, fromInd);
const auto clsEndInd = ClsEnd(bcInd);
const auto bits2Copy = clsEndInd - fromInd;
if (toInd != fromInd)
{
assert(NV(2) || P("Copying the clause: " + SLits(Cls(bcInd)) + " from " + HexStr((TUInd)bcInd) + "," + HexStr(fromInd) + " to " + HexStr(toInd) + ", where " + to_string(bits2Copy) + " bits are copied\n"));
if (NotifyAboutRemainingChunkMove != nullptr)
{
const TBCInd bcToInd(bcHashInd, toInd);
NotifyAboutRemainingChunkMove(bcInd, bcToInd);
}
ba.copy_block(fromInd, toInd, bits2Copy);
}
toInd += bits2Copy;
fromInd += bits2Copy;
}
ba.bit_resize_and_compress(toInd);
}
}
uint16_t m_LastBCBitArrayInd = 0;
CBitArray* m_LastBCBitArrayPtr = nullptr;
inline CBitArray& BCGetBitArray(uint16_t i)
{
CApplyFuncOnExitFromScope<> onExit([&]()
{
m_LastBCBitArrayInd = i;
m_LastBCBitArrayPtr = &m_BC.at(i);
});
return i == m_LastBCBitArrayInd ? *m_LastBCBitArrayPtr : m_BC.at(i);
}
uint16_t m_LastBCBitArrayConstInd = 0;
CBitArray* m_LastBCBitArrayConstPtr = nullptr;
inline const CBitArray& BCGetBitArrayConst(uint16_t i) const
{
CApplyFuncOnExitFromScope<> onExit([&]()
{
const_cast<uint16_t&>(m_LastBCBitArrayConstInd) = i;
});
return i == m_LastBCBitArrayInd ? *m_LastBCBitArrayPtr : m_BC.at(i);
}
inline uint16_t BCMaxLitWidth(span<TULit> cls) const
{
const auto maxElem = *std::max_element(cls.begin(), cls.end());
// This assertion should hold as long as 5 bits are allocated for m_BitsForLit
// For having literals of up to 2^64, it should be sufficient to allocate 6 bits for m_BitsForLit, in which case the assert below should be removed
assert((uint64_t)maxElem <= (uint64_t)0x100000000);
return bit_width(maxElem);
}
// A compressed clause, which simulates a standard vector with literals, given a bit-array
// The main difference from the user perspective is that a seemingly by-value access to CCompressedCls is in fact always by reference.
// For example, the following code will change c[0] to 1000 (the same code wouldn't modify a standard clause)
// CCompressedCls c
// auto l = c[0]
// l = 1000
// whereas, the following code won't compile
// CCompressedCls c
// auto& l = c[0]
// One implication is that it is impossible to design a range-based by-reference for loop for CCls
// (we're using CCls = conditional_t<Compress, CCompressedCls, CStandardCls>)
// , since CCompressedCls requires auto l : c, whereas CStandardCls requires auto& l : c
// Having said all this, much of std functionality is still supported for CCls transparently for the user, including (by example):
// c[3] = 5
// l = c[3]
// auto it = find(im4.begin(), im4.end(), GetLit(16, false));
// remove_if(cls1.begin(), cls1.end(), IsEq);
// transform(cls1.begin(), cls1.end(), cls1.begin(), [&](TULit l) { return l + 1; });
// for (auto it = cls.begin() + 2; it != cls.end(); ++it)
// swap(c[0], c[1]) : implementation required some extra-code; see below
// Need "public" to be able to compile swap overrides with gcc as VS "friend" work-arounds (commented out in this version) do not work there
public:
class CCompressedCls
{
public:
CCompressedCls(CBitArray& ba, TBCInd bcInd) : m_Ba(&ba), m_BCInd(bcInd),
m_ClsSize(BCEncodedClsSize2ClsSize([&]() { return m_Ba->bit_get(bcInd.m_BitStart, bcInd.m_BitsForClsSize); }, bcInd.m_BitsForClsSize)) {
assert(m_ClsSize > 0);
}
bool Update()
{
m_ClsSize = BCEncodedClsSize2ClsSize([&]() { return m_Ba->bit_get(m_BCInd.m_BitStart, m_BCInd.m_BitsForClsSize); }, m_BCInd.m_BitsForClsSize);
return true;
}
class CIteratorRef
{
public:
CIteratorRef(CBitArray* ba, uint64_t startingBit, uint8_t bits2Read) : m_Ba(ba), m_StartingBit(startingBit), m_BitsForLit(bits2Read) { assert(!IsLocal()); }
CIteratorRef(CIteratorRef&& ccir) : m_Ba(nullptr), m_LocalLit((TULit)ccir), m_BitsForLit(ccir.m_BitsForLit) { assert(IsLocal()); }
operator TULit() const
{
return !IsLocal() ? (TULit)m_Ba->bit_get(m_StartingBit, m_BitsForLit) : m_LocalLit;
}
CIteratorRef& operator=(TULit l)
{
assert(!IsLocal());
m_Ba->bit_set(l, m_BitsForLit, m_StartingBit);
return *this;
}
// Move assignment operator
CIteratorRef& operator =(CIteratorRef&& ccirOther)
{
assert(m_BitsForLit == ccirOther.m_BitsForLit);
*this = (TULit)ccirOther;
return *this;
}
// Needed to remove "protected" to be able to compile swap overrides with gcc as VS "friend" work-arounds (commented out in this version) do not work there
//protected:
CBitArray* m_Ba;
union
{
uint64_t m_StartingBit;
TULit m_LocalLit;
};
uint8_t m_BitsForLit;
inline bool IsLocal() const { return m_Ba == nullptr; }
//friend void swap(CTopi::CCompressedCls::CIteratorRef&& ccir1RValue, CTopi::CCompressedCls::CIteratorRef&& ccir2RValue);
//friend void swap(const CTopi::CCompressedCls::CIteratorRef& ccir1LValue, CTopi::CCompressedCls::CIteratorRef&& ccir2RValue);
//friend void swap(CTopi::CCompressedCls::CIteratorRef&& ccir1RValue, const CTopi::CCompressedCls::CIteratorRef& ccir2LValue);
//friend void swap(const CTopi::CCompressedCls::CIteratorRef& ccir1LValue, const CTopi::CCompressedCls::CIteratorRef& ccir2LValue);
};
class CIteratorRefConst
{
public:
CIteratorRefConst(CBitArray* ba, uint64_t startingBit, uint8_t bits2Read) : m_Ba(ba), m_StartingBit(startingBit), m_BitsForLit(bits2Read) {}
operator TULit() const
{
return (TULit)m_Ba->bit_get(m_StartingBit, m_BitsForLit);
}
protected:
CBitArray* m_Ba;
uint64_t m_StartingBit;
uint8_t m_BitsForLit;
};
class TIteratorConst
{
public:
using iterator_category = random_access_iterator_tag;
using difference_type = uint64_t;
using value_type = TULit;
using reference = CIteratorRefConst;
TIteratorConst(CBitArray* ba, uint64_t firstLitBit, uint8_t bitsForLit) :
m_Ba(ba), m_CurrBit(firstLitBit), m_BitsForLit(bitsForLit) {}
const reference operator*()
{
return CIteratorRefConst(m_Ba, m_CurrBit, m_BitsForLit);
}
TIteratorConst& operator++()
{
m_CurrBit += m_BitsForLit;
return *this;
}
TIteratorConst operator+(size_t i) const
{
return TIteratorConst(m_Ba, m_CurrBit + (uint64_t)i * m_BitsForLit, m_BitsForLit);
}
difference_type operator-(const TIteratorConst& it) { return (m_CurrBit - it.m_CurrBit) / m_BitsForLit; }
friend bool operator== (const TIteratorConst& a, const TIteratorConst& b) { return a.m_Ba->get_const_ptr() == b.m_Ba->get_const_ptr() && a.m_CurrBit == b.m_CurrBit && a.m_BitsForLit == b.m_BitsForLit; };
friend bool operator!= (const TIteratorConst& a, const TIteratorConst& b) { return !(a == b); };
protected:
CBitArray* m_Ba;
uint64_t m_CurrBit;
uint8_t m_BitsForLit;
};
class TIterator
{
public:
using iterator_category = random_access_iterator_tag;
using difference_type = uint64_t;
using value_type = TULit;
using reference = CIteratorRef;
TIterator(CBitArray* ba, uint64_t firstLitBit, uint8_t bitsForLit) :
m_Ba(ba), m_CurrBit(firstLitBit), m_BitsForLit(bitsForLit) {}
reference operator*()
{
return CIteratorRef(m_Ba, m_CurrBit, m_BitsForLit);
}
TIterator& operator++()
{
m_CurrBit += m_BitsForLit;
return *this;
}
TIterator operator+(size_t i) const
{
return TIterator(m_Ba, m_CurrBit + (uint64_t)i * m_BitsForLit, m_BitsForLit);
}
difference_type operator-(const TIterator& it) const { return (m_CurrBit - it.m_CurrBit) / m_BitsForLit; }
friend bool operator== (const TIterator& a, const TIterator& b) { return a.m_Ba->get_const_ptr() == b.m_Ba->get_const_ptr() && a.m_CurrBit == b.m_CurrBit && a.m_BitsForLit == b.m_BitsForLit; };
friend bool operator!= (const TIterator& a, const TIterator& b) { return !(a == b); };
protected:
CBitArray* m_Ba;
uint64_t m_CurrBit;
uint8_t m_BitsForLit;
};
TIterator begin()
{
return TIterator(m_Ba, m_BCInd.BitFirstLit(), m_BCInd.m_BitsForLit);
}
TIterator end()
{
return TIterator(m_Ba, m_BCInd.BitFirstLit() + m_BCInd.m_BitsForLit * m_ClsSize, m_BCInd.m_BitsForLit);
}
TIterator::reference operator[](size_t i)
{
return *TIterator(m_Ba, m_BCInd.BitFirstLit() + m_BCInd.m_BitsForLit * i, m_BCInd.m_BitsForLit);
}
TIterator::reference back()
{
return (*this)[m_ClsSize - 1];
}
TIteratorConst begin() const
{
return TIteratorConst(m_Ba, m_BCInd.BitFirstLit(), m_BCInd.m_BitsForLit);
}
TIteratorConst end() const
{
return TIteratorConst(m_Ba, m_BCInd.BitFirstLit() + m_BCInd.m_BitsForLit * m_ClsSize, m_BCInd.m_BitsForLit);
}
TIteratorConst::reference operator[](size_t i) const
{
return *TIteratorConst(m_Ba, m_BCInd.BitFirstLit() + m_BCInd.m_BitsForLit * i, m_BCInd.m_BitsForLit);
}
TIteratorConst::reference back() const
{
return (*this)[m_ClsSize - 1];
}
inline bool IsLearnt() const { return (bool)m_BCInd.m_IsLearnt; }
inline TUV BufferGetGlue() const
{
assert(IsLearnt());
return (TUV)m_Ba->bit_get(m_BCInd.m_BitStart + (uint64_t)m_BCInd.m_BitsForClsSize, m_BCInd.GetBitsGlue());
}
inline void BufferSetGlue(TUV glue)
{
assert(IsLearnt());
m_Ba->bit_set(glue, m_BCInd.GetBitsGlue(), m_BCInd.m_BitStart + (uint64_t)m_BCInd.m_BitsForClsSize);
}
inline bool BufferGetSkipDel() const
{
assert(IsLearnt());
return (bool)m_Ba->bit_get(m_BCInd.m_BitStart + (uint64_t)m_BCInd.m_BitsForClsSize + m_BCInd.GetBitsGlue(), 1);
}
inline void BufferSetSkipDel(bool skipDel)
{
assert(IsLearnt());
m_Ba->bit_set(skipDel, 1, m_BCInd.m_BitStart + (uint64_t)m_BCInd.m_BitsForClsSize + m_BCInd.GetBitsGlue());
}
inline float BufferGetActivity() const
{
assert(IsLearnt());
uint32_t tmpUint32 = (uint32_t)m_Ba->bit_get(m_BCInd.m_BitStart + (uint64_t)m_BCInd.m_BitsForClsSize + m_BCInd.GetBitsGlue() + 1, 31);
return *(float*)&tmpUint32;
}
inline void BufferSetActivity(float activity)
{
assert(IsLearnt());
m_Ba->bit_set(*((uint32_t*)&activity), 31, m_BCInd.m_BitStart + (uint64_t)m_BCInd.m_BitsForClsSize + m_BCInd.GetBitsGlue() + 1);
}
inline size_t size() const { return (size_t)m_ClsSize; }
protected:
CBitArray* m_Ba;
TBCInd m_BCInd;
TBCInd m_ClsSize;
};
protected:
//friend void swap(typename CTopi::CCompressedCls::CIteratorRef&& ccir1RValue, typename CTopi::CCompressedCls::CIteratorRef&& ccir2RValue);
//friend void swap(typename const CTopi::CCompressedCls::CIteratorRef& ccir1LValue, typename CTopi::CCompressedCls::CIteratorRef&& ccir2RValue);
//friend void swap(typename CTopi::CCompressedCls::CIteratorRef&& ccir1RValue, typename const CTopi::CCompressedCls::CIteratorRef& ccir2LValue);
//friend void swap(typename const CTopi::CCompressedCls::CIteratorRef& ccir1LValue, typename const CTopi::CCompressedCls::CIteratorRef& ccir2LValue);
// *** ConstDenseSnapshot ***
// Const: I don't modify
// Snapshot: others don't modify (otherwise, if they do, I'm expected to ignore)
// Dense: visiting all (up to maxLitsNum, if specified) literals
// Properties: always holds a TSpanTULit of the clause's literals
// Notes: in compressed mode, can be implemented by reading all (up to maxLitsNum, if specified) lits upfront into an array (which would then be used for the span)
class CCompressedClsConstSnapshotDense
{
public:
CCompressedClsConstSnapshotDense(const CBitArray& ba, TBCInd bcInd, TUV maxLitsNum = numeric_limits<TUV>::max())
{
const CCompressedCls cc(*const_cast<CBitArray*>(&ba), bcInd);
if (maxLitsNum > cc.size())
{
maxLitsNum = (TUV)cc.size();
}
m_ClsLits.reserve(maxLitsNum);
for (TUV i = 0; i < maxLitsNum; ++i)
{
m_ClsLits.push_back(cc[i]);
}
m_Span = span(m_ClsLits.begin(), m_ClsLits.end());
#ifdef _DEBUG
m_ClsInitially.reserve(m_Span.size());
copy(m_Span.begin(), m_Span.end(), back_inserter(m_ClsInitially));
#endif // DEBUG
}
~CCompressedClsConstSnapshotDense()
{
#ifdef _DEBUG