Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F27033505
Glucose.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Authored By
Unknown
Size
48 KB
Referenced Files
None
Subscribers
None
Glucose.cpp
View Options
/***************************************************************************************[Solver.cc]
Glucose -- Copyright (c) 2013, Gilles Audemard, Laurent Simon
CRIL - Univ. Artois, France
LRI - Univ. Paris Sud, France
Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions and copyrights of
Glucose are exactly the same as Minisat on which it is based on. (see below).
---------------
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#include
<math.h>
#include
"abc/Sort.h"
#include
"abc/Solver.h"
#include
"abc/Constants.h"
#include
"abc/system.h"
ABC_NAMESPACE_IMPL_START
using
namespace
Gluco
;
//=================================================================================================
// Options:
static
const
char
*
_cat
=
"CORE"
;
static
const
char
*
_cr
=
"CORE -- RESTART"
;
static
const
char
*
_cred
=
"CORE -- REDUCE"
;
static
const
char
*
_cm
=
"CORE -- MINIMIZE"
;
static
const
char
*
_certified
=
"CORE -- CERTIFIED UNSAT"
;
const
bool
opt_incremental
=
false
;
const
double
opt_K
=
0.8
;
const
double
opt_R
=
1.4
;
const
int
opt_size_lbd_queue
=
50
;
const
int
opt_first_reduce_db
=
2000
;
const
int
opt_inc_reduce_db
=
300
;
const
int
opt_spec_inc_reduce_db
=
1000
;
const
int
opt_lb_lbd_frozen_clause
=
30
;
const
int
opt_lb_size_minimzing_clause
=
30
;
const
int
opt_lb_lbd_minimzing_clause
=
6
;
const
double
opt_var_decay
=
0.8
;
const
double
opt_clause_decay
=
0.999
;
const
double
opt_random_var_freq
=
0
;
const
double
opt_random_seed
=
91648253
;
const
int
opt_ccmin_mode
=
2
;
const
int
opt_phase_saving
=
2
;
const
bool
opt_rnd_init_act
=
false
;
/*
static IntOption opt_restart_first (_cat, "rfirst", "The base restart interval", 100, IntRange(1, INT32_MAX));
static DoubleOption opt_restart_inc (_cat, "rinc", "Restart interval increase factor", 2, DoubleRange(1, false, HUGE_VAL, false));
*/
const
double
opt_garbage_frac
=
0.20
;
const
bool
opt_certified_
=
false
;
const
char
*
const
opt_certified_file_
=
"NULL"
;
//=================================================================================================
// Constructor/Destructor:
Solver
::
Solver
()
:
// Parameters (user settable):
//
SolverType
(
0
)
,
pCnfFunc
(
NULL
)
,
nCallConfl
(
1000
)
,
terminate_search_early
(
false
)
,
pstop
(
NULL
)
,
nRuntimeLimit
(
0
)
,
verbosity
(
0
)
,
verbEveryConflicts
(
10000
)
,
showModel
(
0
)
,
K
(
opt_K
)
,
R
(
opt_R
)
,
sizeLBDQueue
(
50
)
,
sizeTrailQueue
(
5000
)
,
firstReduceDB
(
opt_first_reduce_db
)
,
incReduceDB
(
opt_inc_reduce_db
)
,
specialIncReduceDB
(
opt_spec_inc_reduce_db
)
,
lbLBDFrozenClause
(
opt_lb_lbd_frozen_clause
)
,
lbSizeMinimizingClause
(
opt_lb_size_minimzing_clause
)
,
lbLBDMinimizingClause
(
opt_lb_lbd_minimzing_clause
)
,
var_decay
(
opt_var_decay
)
,
clause_decay
(
opt_clause_decay
)
,
random_var_freq
(
opt_random_var_freq
)
,
random_seed
(
opt_random_seed
)
,
ccmin_mode
(
opt_ccmin_mode
)
,
phase_saving
(
opt_phase_saving
)
,
rnd_pol
(
false
)
,
rnd_init_act
(
opt_rnd_init_act
)
,
garbage_frac
(
opt_garbage_frac
)
,
certifiedOutput
(
NULL
)
,
certifiedUNSAT
(
opt_certified_
)
// Statistics: (formerly in 'SolverStats')
//
,
nbRemovedClauses
(
0
),
nbReducedClauses
(
0
),
nbDL2
(
0
),
nbBin
(
0
),
nbUn
(
0
)
,
nbReduceDB
(
0
)
,
solves
(
0
),
starts
(
0
),
decisions
(
0
),
rnd_decisions
(
0
),
propagations
(
0
),
conflicts
(
0
),
conflictsRestarts
(
0
),
nbstopsrestarts
(
0
),
nbstopsrestartssame
(
0
),
lastblockatrestart
(
0
)
,
dec_vars
(
0
),
clauses_literals
(
0
),
learnts_literals
(
0
),
max_literals
(
0
),
tot_literals
(
0
)
,
curRestart
(
1
)
,
ok
(
true
)
,
cla_inc
(
1
)
,
var_inc
(
1
)
,
watches
(
WatcherDeleted
(
ca
))
,
watchesBin
(
WatcherDeleted
(
ca
))
,
qhead
(
0
)
,
simpDB_assigns
(
-1
)
,
simpDB_props
(
0
)
,
order_heap
(
VarOrderLt
(
activity
))
,
progress_estimate
(
0
)
,
remove_satisfied
(
true
)
// Resource constraints:
//
,
conflict_budget
(
-1
)
,
propagation_budget
(
-1
)
,
asynch_interrupt
(
false
)
,
incremental
(
opt_incremental
)
,
nbVarsInitialFormula
(
INT32_MAX
)
{
MYFLAG
=
0
;
// Initialize only first time. Useful for incremental solving, useless otherwise
lbdQueue
.
initSize
(
sizeLBDQueue
);
trailQueue
.
initSize
(
sizeTrailQueue
);
sumLBD
=
0
;
nbclausesbeforereduce
=
firstReduceDB
;
totalTime4Sat
=
0
;
totalTime4Unsat
=
0
;
nbSatCalls
=
0
;
nbUnsatCalls
=
0
;
if
(
certifiedUNSAT
)
{
if
(
!
strcmp
(
opt_certified_file_
,
"NULL"
))
{
certifiedOutput
=
fopen
(
"/dev/stdout"
,
"wb"
);
}
else
{
certifiedOutput
=
fopen
(
opt_certified_file_
,
"wb"
);
}
// fprintf(certifiedOutput,"o proof DRUP\n");
}
}
Solver
::~
Solver
()
{
}
/****************************************************************
Set the incremental mode
****************************************************************/
// This function set the incremental mode to true.
// You can add special code for this mode here.
void
Solver
::
setIncrementalMode
()
{
incremental
=
true
;
}
// Number of variables without selectors
void
Solver
::
initNbInitialVars
(
int
nb
)
{
nbVarsInitialFormula
=
nb
;
}
//=================================================================================================
// Minor methods:
// Creates a new SAT variable in the solver. If 'decision' is cleared, variable will not be
// used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result).
//
Var
Solver
::
newVar
(
bool
sign
,
bool
dvar
)
{
int
v
=
nVars
();
watches
.
init
(
mkLit
(
v
,
false
));
watches
.
init
(
mkLit
(
v
,
true
));
watchesBin
.
init
(
mkLit
(
v
,
false
));
watchesBin
.
init
(
mkLit
(
v
,
true
));
assigns
.
push
(
l_Undef
);
vardata
.
push
(
mkVarData
(
CRef_Undef
,
0
));
//activity .push(0);
activity
.
push
(
rnd_init_act
?
drand
(
random_seed
)
*
0.00001
:
0
);
seen
.
push
(
0
);
permDiff
.
push
(
0
);
polarity
.
push
(
sign
);
decision
.
push
();
trail
.
capacity
(
v
+
1
);
setDecisionVar
(
v
,
dvar
);
return
v
;
}
bool
Solver
::
addClause_
(
vec
<
Lit
>&
ps
)
{
assert
(
decisionLevel
()
==
0
);
if
(
!
ok
)
return
false
;
if
(
0
)
{
for
(
int
i
=
0
;
i
<
ps
.
size
();
i
++
)
printf
(
"%s%d "
,
(
toInt
(
ps
[
i
])
&
1
)
?
"-"
:
""
,
toInt
(
ps
[
i
])
>>
1
);
printf
(
"
\n
"
);
}
// Check if clause is satisfied and remove false/duplicate literals:
sort
(
ps
);
vec
<
Lit
>
oc
;
oc
.
clear
();
Lit
p
;
int
i
,
j
,
flag
=
0
;
if
(
certifiedUNSAT
)
{
for
(
i
=
j
=
0
,
p
=
lit_Undef
;
i
<
ps
.
size
();
i
++
)
{
oc
.
push
(
ps
[
i
]);
if
(
value
(
ps
[
i
])
==
l_True
||
ps
[
i
]
==
~
p
||
value
(
ps
[
i
])
==
l_False
)
flag
=
1
;
}
}
for
(
i
=
j
=
0
,
p
=
lit_Undef
;
i
<
ps
.
size
();
i
++
)
if
(
value
(
ps
[
i
])
==
l_True
||
ps
[
i
]
==
~
p
)
return
true
;
else
if
(
value
(
ps
[
i
])
!=
l_False
&&
ps
[
i
]
!=
p
)
ps
[
j
++
]
=
p
=
ps
[
i
];
ps
.
shrink
(
i
-
j
);
if
(
0
)
{
for
(
int
i
=
0
;
i
<
ps
.
size
();
i
++
)
printf
(
"%s%d "
,
(
toInt
(
ps
[
i
])
&
1
)
?
"-"
:
""
,
toInt
(
ps
[
i
])
>>
1
);
printf
(
"
\n
"
);
}
if
(
flag
&&
(
certifiedUNSAT
))
{
for
(
i
=
j
=
0
,
p
=
lit_Undef
;
i
<
ps
.
size
();
i
++
)
fprintf
(
certifiedOutput
,
"%i "
,
(
var
(
ps
[
i
])
+
1
)
*
(
-2
*
sign
(
ps
[
i
])
+
1
));
fprintf
(
certifiedOutput
,
"0
\n
"
);
fprintf
(
certifiedOutput
,
"d "
);
for
(
i
=
j
=
0
,
p
=
lit_Undef
;
i
<
oc
.
size
();
i
++
)
fprintf
(
certifiedOutput
,
"%i "
,
(
var
(
oc
[
i
])
+
1
)
*
(
-2
*
sign
(
oc
[
i
])
+
1
));
fprintf
(
certifiedOutput
,
"0
\n
"
);
}
if
(
ps
.
size
()
==
0
)
return
ok
=
false
;
else
if
(
ps
.
size
()
==
1
){
uncheckedEnqueue
(
ps
[
0
]);
return
ok
=
(
propagate
()
==
CRef_Undef
);
}
else
{
CRef
cr
=
ca
.
alloc
(
ps
,
false
);
clauses
.
push
(
cr
);
attachClause
(
cr
);
}
return
true
;
}
void
Solver
::
attachClause
(
CRef
cr
)
{
const
Clause
&
c
=
ca
[
cr
];
assert
(
c
.
size
()
>
1
);
if
(
c
.
size
()
==
2
)
{
watchesBin
[
~
c
[
0
]].
push
(
Watcher
(
cr
,
c
[
1
]));
watchesBin
[
~
c
[
1
]].
push
(
Watcher
(
cr
,
c
[
0
]));
}
else
{
watches
[
~
c
[
0
]].
push
(
Watcher
(
cr
,
c
[
1
]));
watches
[
~
c
[
1
]].
push
(
Watcher
(
cr
,
c
[
0
]));
}
if
(
c
.
learnt
())
learnts_literals
+=
c
.
size
();
else
clauses_literals
+=
c
.
size
();
}
void
Solver
::
detachClause
(
CRef
cr
,
bool
strict
)
{
const
Clause
&
c
=
ca
[
cr
];
assert
(
c
.
size
()
>
1
);
if
(
c
.
size
()
==
2
)
{
if
(
strict
){
remove
(
watchesBin
[
~
c
[
0
]],
Watcher
(
cr
,
c
[
1
]));
remove
(
watchesBin
[
~
c
[
1
]],
Watcher
(
cr
,
c
[
0
]));
}
else
{
// Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause)
watchesBin
.
smudge
(
~
c
[
0
]);
watchesBin
.
smudge
(
~
c
[
1
]);
}
}
else
{
if
(
strict
){
remove
(
watches
[
~
c
[
0
]],
Watcher
(
cr
,
c
[
1
]));
remove
(
watches
[
~
c
[
1
]],
Watcher
(
cr
,
c
[
0
]));
}
else
{
// Lazy detaching: (NOTE! Must clean all watcher lists before garbage collecting this clause)
watches
.
smudge
(
~
c
[
0
]);
watches
.
smudge
(
~
c
[
1
]);
}
}
if
(
c
.
learnt
())
learnts_literals
-=
c
.
size
();
else
clauses_literals
-=
c
.
size
();
}
void
Solver
::
removeClause
(
CRef
cr
)
{
Clause
&
c
=
ca
[
cr
];
if
(
certifiedUNSAT
)
{
fprintf
(
certifiedOutput
,
"d "
);
for
(
int
i
=
0
;
i
<
c
.
size
();
i
++
)
fprintf
(
certifiedOutput
,
"%i "
,
(
var
(
c
[
i
])
+
1
)
*
(
-2
*
sign
(
c
[
i
])
+
1
));
fprintf
(
certifiedOutput
,
"0
\n
"
);
}
detachClause
(
cr
);
// Don't leave pointers to free'd memory!
if
(
locked
(
c
))
vardata
[
var
(
c
[
0
])].
reason
=
CRef_Undef
;
c
.
mark
(
1
);
ca
.
free_
(
cr
);
}
bool
Solver
::
satisfied
(
const
Clause
&
c
)
const
{
if
(
incremental
)
// Check clauses with many selectors is too time consuming
return
(
value
(
c
[
0
])
==
l_True
)
||
(
value
(
c
[
1
])
==
l_True
);
// Default mode.
for
(
int
i
=
0
;
i
<
c
.
size
();
i
++
)
if
(
value
(
c
[
i
])
==
l_True
)
return
true
;
return
false
;
}
/************************************************************
* Compute LBD functions
*************************************************************/
inline
unsigned
int
Solver
::
computeLBD
(
const
vec
<
Lit
>
&
lits
,
int
end
)
{
int
nblevels
=
0
;
MYFLAG
++
;
if
(
incremental
)
{
// ----------------- INCREMENTAL MODE
if
(
end
==
-1
)
end
=
lits
.
size
();
unsigned
int
nbDone
=
0
;
for
(
int
i
=
0
;
i
<
lits
.
size
();
i
++
)
{
if
(
nbDone
>=
end
)
break
;
if
(
isSelector
(
var
(
lits
[
i
])))
continue
;
nbDone
++
;
int
l
=
level
(
var
(
lits
[
i
]));
if
(
permDiff
[
l
]
!=
MYFLAG
)
{
permDiff
[
l
]
=
MYFLAG
;
nblevels
++
;
}
}
}
else
{
// -------- DEFAULT MODE. NOT A LOT OF DIFFERENCES... BUT EASIER TO READ
for
(
int
i
=
0
;
i
<
lits
.
size
();
i
++
)
{
int
l
=
level
(
var
(
lits
[
i
]));
if
(
permDiff
[
l
]
!=
MYFLAG
)
{
permDiff
[
l
]
=
MYFLAG
;
nblevels
++
;
}
}
}
return
nblevels
;
}
inline
unsigned
int
Solver
::
computeLBD
(
const
Clause
&
c
)
{
int
nblevels
=
0
;
MYFLAG
++
;
if
(
incremental
)
{
// ----------------- INCREMENTAL MODE
int
nbDone
=
0
;
for
(
int
i
=
0
;
i
<
c
.
size
();
i
++
)
{
if
(
nbDone
>=
c
.
sizeWithoutSelectors
())
break
;
if
(
isSelector
(
var
(
c
[
i
])))
continue
;
nbDone
++
;
int
l
=
level
(
var
(
c
[
i
]));
if
(
permDiff
[
l
]
!=
MYFLAG
)
{
permDiff
[
l
]
=
MYFLAG
;
nblevels
++
;
}
}
}
else
{
// -------- DEFAULT MODE. NOT A LOT OF DIFFERENCES... BUT EASIER TO READ
for
(
int
i
=
0
;
i
<
c
.
size
();
i
++
)
{
int
l
=
level
(
var
(
c
[
i
]));
if
(
permDiff
[
l
]
!=
MYFLAG
)
{
permDiff
[
l
]
=
MYFLAG
;
nblevels
++
;
}
}
}
return
nblevels
;
}
/******************************************************************
* Minimisation with binary reolution
******************************************************************/
void
Solver
::
minimisationWithBinaryResolution
(
vec
<
Lit
>
&
out_learnt
)
{
// Find the LBD measure
unsigned
int
lbd
=
computeLBD
(
out_learnt
);
Lit
p
=
~
out_learnt
[
0
];
if
(
lbd
<=
lbLBDMinimizingClause
){
MYFLAG
++
;
for
(
int
i
=
1
;
i
<
out_learnt
.
size
();
i
++
)
{
permDiff
[
var
(
out_learnt
[
i
])]
=
MYFLAG
;
}
vec
<
Watcher
>&
wbin
=
watchesBin
[
p
];
int
nb
=
0
;
for
(
int
k
=
0
;
k
<
wbin
.
size
();
k
++
)
{
Lit
imp
=
wbin
[
k
].
blocker
;
if
(
permDiff
[
var
(
imp
)]
==
MYFLAG
&&
value
(
imp
)
==
l_True
)
{
nb
++
;
permDiff
[
var
(
imp
)]
=
MYFLAG
-1
;
}
}
int
l
=
out_learnt
.
size
()
-1
;
if
(
nb
>
0
)
{
nbReducedClauses
++
;
for
(
int
i
=
1
;
i
<
out_learnt
.
size
()
-
nb
;
i
++
)
{
if
(
permDiff
[
var
(
out_learnt
[
i
])]
!=
MYFLAG
)
{
Lit
p
=
out_learnt
[
l
];
out_learnt
[
l
]
=
out_learnt
[
i
];
out_learnt
[
i
]
=
p
;
l
--
;
i
--
;
}
}
out_learnt
.
shrink
(
nb
);
}
}
}
// Revert to the state at given level (keeping all assignment at 'level' but not beyond).
//
void
Solver
::
cancelUntil
(
int
level
)
{
if
(
decisionLevel
()
>
level
){
for
(
int
c
=
trail
.
size
()
-1
;
c
>=
trail_lim
[
level
];
c
--
){
Var
x
=
var
(
trail
[
c
]);
assigns
[
x
]
=
l_Undef
;
if
(
phase_saving
>
1
||
((
phase_saving
==
1
)
&&
c
>
trail_lim
.
last
()))
polarity
[
x
]
=
sign
(
trail
[
c
]);
insertVarOrder
(
x
);
}
qhead
=
trail_lim
[
level
];
trail
.
shrink
(
trail
.
size
()
-
trail_lim
[
level
]);
trail_lim
.
shrink
(
trail_lim
.
size
()
-
level
);
}
}
//=================================================================================================
// Major methods:
Lit
Solver
::
pickBranchLit
()
{
Var
next
=
var_Undef
;
// Random decision:
if
(
drand
(
random_seed
)
<
random_var_freq
&&
!
order_heap
.
empty
()){
next
=
order_heap
[
irand
(
random_seed
,
order_heap
.
size
())];
if
(
value
(
next
)
==
l_Undef
&&
decision
[
next
])
rnd_decisions
++
;
}
// Activity based decision:
while
(
next
==
var_Undef
||
value
(
next
)
!=
l_Undef
||
!
decision
[
next
])
if
(
order_heap
.
empty
()){
next
=
var_Undef
;
break
;
}
else
next
=
order_heap
.
removeMin
();
return
next
==
var_Undef
?
lit_Undef
:
mkLit
(
next
,
rnd_pol
?
drand
(
random_seed
)
<
0.5
:
(
polarity
[
next
]
!=
0
));
}
/*_________________________________________________________________________________________________
|
| analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void]
|
| Description:
| Analyze conflict and produce a reason clause.
|
| Pre-conditions:
| * 'out_learnt' is assumed to be cleared.
| * Current decision level must be greater than root level.
|
| Post-conditions:
| * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'.
| * If out_learnt.size() > 1 then 'out_learnt[1]' has the greatest decision level of the
| rest of literals. There may be others from the same level though.
|
|________________________________________________________________________________________________@*/
void
Solver
::
analyze
(
CRef
confl
,
vec
<
Lit
>&
out_learnt
,
vec
<
Lit
>&
selectors
,
int
&
out_btlevel
,
unsigned
int
&
lbd
,
unsigned
int
&
szWithoutSelectors
)
{
int
pathC
=
0
;
Lit
p
=
lit_Undef
;
// Generate conflict clause:
//
out_learnt
.
push
();
// (leave room for the asserting literal)
int
index
=
trail
.
size
()
-
1
;
do
{
assert
(
confl
!=
CRef_Undef
);
// (otherwise should be UIP)
Clause
&
c
=
ca
[
confl
];
// Special case for binary clauses
// The first one has to be SAT
if
(
p
!=
lit_Undef
&&
c
.
size
()
==
2
&&
value
(
c
[
0
])
==
l_False
)
{
assert
(
value
(
c
[
1
])
==
l_True
);
Lit
tmp
=
c
[
0
];
c
[
0
]
=
c
[
1
],
c
[
1
]
=
tmp
;
}
if
(
c
.
learnt
())
claBumpActivity
(
c
);
#ifdef DYNAMICNBLEVEL
// DYNAMIC NBLEVEL trick (see competition'09 companion paper)
if
(
c
.
learnt
()
&&
c
.
lbd
()
>
2
)
{
unsigned
int
nblevels
=
computeLBD
(
c
);
if
(
nblevels
+
1
<
c
.
lbd
()
)
{
// improve the LBD
if
(
c
.
lbd
()
<=
lbLBDFrozenClause
)
{
c
.
setCanBeDel
(
false
);
}
// seems to be interesting : keep it for the next round
c
.
setLBD
(
nblevels
);
// Update it
}
}
#endif
for
(
int
j
=
(
p
==
lit_Undef
)
?
0
:
1
;
j
<
c
.
size
();
j
++
){
Lit
q
=
c
[
j
];
if
(
!
seen
[
var
(
q
)]
&&
level
(
var
(
q
))
>
0
){
if
(
!
isSelector
(
var
(
q
)))
varBumpActivity
(
var
(
q
));
seen
[
var
(
q
)]
=
1
;
if
(
level
(
var
(
q
))
>=
decisionLevel
())
{
pathC
++
;
#ifdef UPDATEVARACTIVITY
// UPDATEVARACTIVITY trick (see competition'09 companion paper)
if
(
!
isSelector
(
var
(
q
))
&&
(
reason
(
var
(
q
))
!=
CRef_Undef
)
&&
ca
[
reason
(
var
(
q
))].
learnt
())
lastDecisionLevel
.
push
(
q
);
#endif
}
else
{
if
(
isSelector
(
var
(
q
)))
{
assert
(
value
(
q
)
==
l_False
);
selectors
.
push
(
q
);
}
else
out_learnt
.
push
(
q
);
}
}
}
// Select next clause to look at:
while
(
!
seen
[
var
(
trail
[
index
--
])]);
p
=
trail
[
index
+
1
];
confl
=
reason
(
var
(
p
));
seen
[
var
(
p
)]
=
0
;
pathC
--
;
}
while
(
pathC
>
0
);
out_learnt
[
0
]
=
~
p
;
// Simplify conflict clause:
//
int
i
,
j
;
for
(
i
=
0
;
i
<
selectors
.
size
();
i
++
)
out_learnt
.
push
(
selectors
[
i
]);
out_learnt
.
copyTo
(
analyze_toclear
);
if
(
ccmin_mode
==
2
){
uint32_t
abstract_level
=
0
;
for
(
i
=
1
;
i
<
out_learnt
.
size
();
i
++
)
abstract_level
|=
abstractLevel
(
var
(
out_learnt
[
i
]));
// (maintain an abstraction of levels involved in conflict)
for
(
i
=
j
=
1
;
i
<
out_learnt
.
size
();
i
++
)
if
(
reason
(
var
(
out_learnt
[
i
]))
==
CRef_Undef
||
!
litRedundant
(
out_learnt
[
i
],
abstract_level
))
out_learnt
[
j
++
]
=
out_learnt
[
i
];
}
else
if
(
ccmin_mode
==
1
){
for
(
i
=
j
=
1
;
i
<
out_learnt
.
size
();
i
++
){
Var
x
=
var
(
out_learnt
[
i
]);
if
(
reason
(
x
)
==
CRef_Undef
)
out_learnt
[
j
++
]
=
out_learnt
[
i
];
else
{
Clause
&
c
=
ca
[
reason
(
var
(
out_learnt
[
i
]))];
// Thanks to Siert Wieringa for this bug fix!
for
(
int
k
=
((
c
.
size
()
==
2
)
?
0
:
1
);
k
<
c
.
size
();
k
++
)
if
(
!
seen
[
var
(
c
[
k
])]
&&
level
(
var
(
c
[
k
]))
>
0
){
out_learnt
[
j
++
]
=
out_learnt
[
i
];
break
;
}
}
}
}
else
i
=
j
=
out_learnt
.
size
();
max_literals
+=
out_learnt
.
size
();
out_learnt
.
shrink
(
i
-
j
);
tot_literals
+=
out_learnt
.
size
();
/* ***************************************
Minimisation with binary clauses of the asserting clause
First of all : we look for small clauses
Then, we reduce clauses with small LBD.
Otherwise, this can be useless
*/
if
(
!
incremental
&&
out_learnt
.
size
()
<=
lbSizeMinimizingClause
)
{
minimisationWithBinaryResolution
(
out_learnt
);
}
// Find correct backtrack level:
//
if
(
out_learnt
.
size
()
==
1
)
out_btlevel
=
0
;
else
{
int
max_i
=
1
;
// Find the first literal assigned at the next-highest level:
for
(
int
i
=
2
;
i
<
out_learnt
.
size
();
i
++
)
if
(
level
(
var
(
out_learnt
[
i
]))
>
level
(
var
(
out_learnt
[
max_i
])))
max_i
=
i
;
// Swap-in this literal at index 1:
Lit
p
=
out_learnt
[
max_i
];
out_learnt
[
max_i
]
=
out_learnt
[
1
];
out_learnt
[
1
]
=
p
;
out_btlevel
=
level
(
var
(
p
));
}
// Compute the size of the clause without selectors (incremental mode)
if
(
incremental
)
{
szWithoutSelectors
=
0
;
for
(
int
i
=
0
;
i
<
out_learnt
.
size
();
i
++
)
{
if
(
!
isSelector
(
var
((
out_learnt
[
i
]))))
szWithoutSelectors
++
;
else
if
(
i
>
0
)
break
;
}
}
else
szWithoutSelectors
=
out_learnt
.
size
();
// Compute LBD
lbd
=
computeLBD
(
out_learnt
,
out_learnt
.
size
()
-
selectors
.
size
());
#ifdef UPDATEVARACTIVITY
// UPDATEVARACTIVITY trick (see competition'09 companion paper)
if
(
lastDecisionLevel
.
size
()
>
0
)
{
for
(
int
i
=
0
;
i
<
lastDecisionLevel
.
size
();
i
++
)
{
if
(
ca
[
reason
(
var
(
lastDecisionLevel
[
i
]))].
lbd
()
<
lbd
)
varBumpActivity
(
var
(
lastDecisionLevel
[
i
]));
}
lastDecisionLevel
.
clear
();
}
#endif
for
(
j
=
0
;
j
<
analyze_toclear
.
size
();
j
++
)
seen
[
var
(
analyze_toclear
[
j
])]
=
0
;
// ('seen[]' is now cleared)
for
(
j
=
0
;
j
<
selectors
.
size
()
;
j
++
)
seen
[
var
(
selectors
[
j
])]
=
0
;
}
// Check if 'p' can be removed. 'abstract_levels' is used to abort early if the algorithm is
// visiting literals at levels that cannot be removed later.
bool
Solver
::
litRedundant
(
Lit
p
,
uint32_t
abstract_levels
)
{
analyze_stack
.
clear
();
analyze_stack
.
push
(
p
);
int
top
=
analyze_toclear
.
size
();
while
(
analyze_stack
.
size
()
>
0
){
assert
(
reason
(
var
(
analyze_stack
.
last
()))
!=
CRef_Undef
);
Clause
&
c
=
ca
[
reason
(
var
(
analyze_stack
.
last
()))];
analyze_stack
.
pop
();
if
(
c
.
size
()
==
2
&&
value
(
c
[
0
])
==
l_False
)
{
assert
(
value
(
c
[
1
])
==
l_True
);
Lit
tmp
=
c
[
0
];
c
[
0
]
=
c
[
1
],
c
[
1
]
=
tmp
;
}
for
(
int
i
=
1
;
i
<
c
.
size
();
i
++
){
Lit
p
=
c
[
i
];
if
(
!
seen
[
var
(
p
)]
&&
level
(
var
(
p
))
>
0
){
if
(
reason
(
var
(
p
))
!=
CRef_Undef
&&
(
abstractLevel
(
var
(
p
))
&
abstract_levels
)
!=
0
){
seen
[
var
(
p
)]
=
1
;
analyze_stack
.
push
(
p
);
analyze_toclear
.
push
(
p
);
}
else
{
for
(
int
j
=
top
;
j
<
analyze_toclear
.
size
();
j
++
)
seen
[
var
(
analyze_toclear
[
j
])]
=
0
;
analyze_toclear
.
shrink
(
analyze_toclear
.
size
()
-
top
);
return
false
;
}
}
}
}
return
true
;
}
/*_________________________________________________________________________________________________
|
| analyzeFinal : (p : Lit) -> [void]
|
| Description:
| Specialized analysis procedure to express the final conflict in terms of assumptions.
| Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and
| stores the result in 'out_conflict'.
|________________________________________________________________________________________________@*/
void
Solver
::
analyzeFinal
(
Lit
p
,
vec
<
Lit
>&
out_conflict
)
{
out_conflict
.
clear
();
out_conflict
.
push
(
p
);
if
(
decisionLevel
()
==
0
)
return
;
seen
[
var
(
p
)]
=
1
;
for
(
int
i
=
trail
.
size
()
-1
;
i
>=
trail_lim
[
0
];
i
--
){
Var
x
=
var
(
trail
[
i
]);
if
(
seen
[
x
]){
if
(
reason
(
x
)
==
CRef_Undef
){
assert
(
level
(
x
)
>
0
);
out_conflict
.
push
(
~
trail
[
i
]);
}
else
{
Clause
&
c
=
ca
[
reason
(
x
)];
// for (int j = 1; j < c.size(); j++) Minisat (glucose 2.0) loop
// Bug in case of assumptions due to special data structures for Binary.
// Many thanks to Sam Bayless (sbayless@cs.ubc.ca) for discover this bug.
for
(
int
j
=
((
c
.
size
()
==
2
)
?
0
:
1
);
j
<
c
.
size
();
j
++
)
if
(
level
(
var
(
c
[
j
]))
>
0
)
seen
[
var
(
c
[
j
])]
=
1
;
}
seen
[
x
]
=
0
;
}
}
seen
[
var
(
p
)]
=
0
;
}
void
Solver
::
uncheckedEnqueue
(
Lit
p
,
CRef
from
)
{
assert
(
value
(
p
)
==
l_Undef
);
assigns
[
var
(
p
)]
=
lbool
(
!
sign
(
p
));
vardata
[
var
(
p
)]
=
mkVarData
(
from
,
decisionLevel
());
trail
.
push_
(
p
);
}
/*_________________________________________________________________________________________________
|
| propagate : [void] -> [Clause*]
|
| Description:
| Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned,
| otherwise CRef_Undef.
|
| Post-conditions:
| * the propagation queue is empty, even if there was a conflict.
|________________________________________________________________________________________________@*/
CRef
Solver
::
propagate
()
{
CRef
confl
=
CRef_Undef
;
int
num_props
=
0
;
watches
.
cleanAll
();
watchesBin
.
cleanAll
();
while
(
qhead
<
trail
.
size
()){
Lit
p
=
trail
[
qhead
++
];
// 'p' is enqueued fact to propagate.
vec
<
Watcher
>&
ws
=
watches
[
p
];
Watcher
*
i
,
*
j
,
*
end
;
num_props
++
;
// First, Propagate binary clauses
vec
<
Watcher
>&
wbin
=
watchesBin
[
p
];
for
(
int
k
=
0
;
k
<
wbin
.
size
();
k
++
)
{
Lit
imp
=
wbin
[
k
].
blocker
;
if
(
value
(
imp
)
==
l_False
)
{
return
wbin
[
k
].
cref
;
}
if
(
value
(
imp
)
==
l_Undef
)
{
uncheckedEnqueue
(
imp
,
wbin
[
k
].
cref
);
}
}
for
(
i
=
j
=
(
Watcher
*
)
ws
,
end
=
i
+
ws
.
size
();
i
!=
end
;){
// Try to avoid inspecting the clause:
Lit
blocker
=
i
->
blocker
;
if
(
value
(
blocker
)
==
l_True
){
*
j
++
=
*
i
++
;
continue
;
}
// Make sure the false literal is data[1]:
CRef
cr
=
i
->
cref
;
Clause
&
c
=
ca
[
cr
];
Lit
false_lit
=
~
p
;
if
(
c
[
0
]
==
false_lit
)
c
[
0
]
=
c
[
1
],
c
[
1
]
=
false_lit
;
assert
(
c
[
1
]
==
false_lit
);
i
++
;
// If 0th watch is true, then clause is already satisfied.
Lit
first
=
c
[
0
];
Watcher
w
=
Watcher
(
cr
,
first
);
if
(
first
!=
blocker
&&
value
(
first
)
==
l_True
){
*
j
++
=
w
;
continue
;
}
// Look for new watch:
if
(
incremental
)
{
// ----------------- INCREMENTAL MODE
int
choosenPos
=
-1
;
for
(
int
k
=
2
;
k
<
c
.
size
();
k
++
)
{
if
(
value
(
c
[
k
])
!=
l_False
){
if
(
decisionLevel
()
>
assumptions
.
size
())
{
choosenPos
=
k
;
break
;
}
else
{
choosenPos
=
k
;
if
(
value
(
c
[
k
])
==
l_True
||
!
isSelector
(
var
(
c
[
k
])))
{
break
;
}
}
}
}
if
(
choosenPos
!=
-1
)
{
c
[
1
]
=
c
[
choosenPos
];
c
[
choosenPos
]
=
false_lit
;
watches
[
~
c
[
1
]].
push
(
w
);
goto
NextClause
;
}
}
else
{
// ----------------- DEFAULT MODE (NOT INCREMENTAL)
for
(
int
k
=
2
;
k
<
c
.
size
();
k
++
)
{
if
(
value
(
c
[
k
])
!=
l_False
){
c
[
1
]
=
c
[
k
];
c
[
k
]
=
false_lit
;
watches
[
~
c
[
1
]].
push
(
w
);
goto
NextClause
;
}
}
}
// Did not find watch -- clause is unit under assignment:
*
j
++
=
w
;
if
(
value
(
first
)
==
l_False
){
confl
=
cr
;
qhead
=
trail
.
size
();
// Copy the remaining watches:
while
(
i
<
end
)
*
j
++
=
*
i
++
;
}
else
{
uncheckedEnqueue
(
first
,
cr
);
}
NextClause
:;
}
ws
.
shrink
(
i
-
j
);
}
propagations
+=
num_props
;
simpDB_props
-=
num_props
;
return
confl
;
}
/*_________________________________________________________________________________________________
|
| reduceDB : () -> [void]
|
| Description:
| Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked
| clauses are clauses that are reason to some assignment. Binary clauses are never removed.
|________________________________________________________________________________________________@*/
struct
reduceDB_lt
{
ClauseAllocator
&
ca
;
reduceDB_lt
(
ClauseAllocator
&
ca_
)
:
ca
(
ca_
)
{}
bool
operator
()
(
CRef
x
,
CRef
y
)
{
// Main criteria... Like in MiniSat we keep all binary clauses
if
(
ca
[
x
].
size
()
>
2
&&
ca
[
y
].
size
()
==
2
)
return
1
;
if
(
ca
[
y
].
size
()
>
2
&&
ca
[
x
].
size
()
==
2
)
return
0
;
if
(
ca
[
x
].
size
()
==
2
&&
ca
[
y
].
size
()
==
2
)
return
0
;
// Second one based on literal block distance
if
(
ca
[
x
].
lbd
()
>
ca
[
y
].
lbd
())
return
1
;
if
(
ca
[
x
].
lbd
()
<
ca
[
y
].
lbd
())
return
0
;
// Finally we can use old activity or size, we choose the last one
return
ca
[
x
].
activity
()
<
ca
[
y
].
activity
();
//return x->size() < y->size();
//return ca[x].size() > 2 && (ca[y].size() == 2 || ca[x].activity() < ca[y].activity()); }
}
};
void
Solver::reduceDB
()
{
int
i
,
j
;
nbReduceDB
++
;
sort
(
learnts
,
reduceDB_lt
(
ca
));
// We have a lot of "good" clauses, it is difficult to compare them. Keep more !
if
(
ca
[
learnts
[
learnts
.
size
()
/
RATIOREMOVECLAUSES
]].
lbd
()
<=
3
)
nbclausesbeforereduce
+=
specialIncReduceDB
;
// Useless :-)
if
(
ca
[
learnts
.
last
()].
lbd
()
<=
5
)
nbclausesbeforereduce
+=
specialIncReduceDB
;
// Don't delete binary or locked clauses. From the rest, delete clauses from the first half
// Keep clauses which seem to be usefull (their lbd was reduce during this sequence)
int
limit
=
learnts
.
size
()
/
2
;
for
(
i
=
j
=
0
;
i
<
learnts
.
size
();
i
++
){
Clause
&
c
=
ca
[
learnts
[
i
]];
if
(
c
.
lbd
()
>
2
&&
c
.
size
()
>
2
&&
c
.
canBeDel
()
&&
!
locked
(
c
)
&&
(
i
<
limit
))
{
removeClause
(
learnts
[
i
]);
nbRemovedClauses
++
;
}
else
{
if
(
!
c
.
canBeDel
())
limit
++
;
//we keep c, so we can delete an other clause
c
.
setCanBeDel
(
true
);
// At the next step, c can be delete
learnts
[
j
++
]
=
learnts
[
i
];
}
}
learnts
.
shrink
(
i
-
j
);
checkGarbage
();
}
void
Solver::removeSatisfied
(
vec
<
CRef
>&
cs
)
{
int
i
,
j
;
for
(
i
=
j
=
0
;
i
<
cs
.
size
();
i
++
){
Clause
&
c
=
ca
[
cs
[
i
]];
if
(
satisfied
(
c
))
removeClause
(
cs
[
i
]);
else
cs
[
j
++
]
=
cs
[
i
];
}
cs
.
shrink
(
i
-
j
);
}
void
Solver::rebuildOrderHeap
()
{
vec
<
Var
>
vs
;
for
(
Var
v
=
0
;
v
<
nVars
();
v
++
)
if
(
decision
[
v
]
&&
value
(
v
)
==
l_Undef
)
vs
.
push
(
v
);
order_heap
.
build
(
vs
);
}
/*_________________________________________________________________________________________________
|
| simplify : [void] -> [bool]
|
| Description:
| Simplify the clause database according to the current top-level assigment. Currently, the only
| thing done here is the removal of satisfied clauses, but more things can be put here.
|________________________________________________________________________________________________@*/
bool
Solver::simplify
()
{
assert
(
decisionLevel
()
==
0
);
if
(
!
ok
||
propagate
()
!=
CRef_Undef
)
return
ok
=
false
;
if
(
nAssigns
()
==
simpDB_assigns
||
(
simpDB_props
>
0
))
return
true
;
// Remove satisfied clauses:
removeSatisfied
(
learnts
);
if
(
remove_satisfied
)
// Can be turned off.
removeSatisfied
(
clauses
);
checkGarbage
();
rebuildOrderHeap
();
simpDB_assigns
=
nAssigns
();
simpDB_props
=
clauses_literals
+
learnts_literals
;
// (shouldn't depend on stats really, but it will do for now)
return
true
;
}
/*_________________________________________________________________________________________________
|
| search : (nof_conflicts : int) (params : const SearchParams&) -> [lbool]
|
| Description:
| Search for a model the specified number of conflicts.
| NOTE! Use negative value for 'nof_conflicts' indicate infinity.
|
| Output:
| 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If
| all variables are decision variables, this means that the clause set is satisfiable. 'l_False'
| if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached.
|________________________________________________________________________________________________@*/
lbool
Solver::search
(
int
nof_conflicts
)
{
assert
(
ok
);
int
backtrack_level
;
int
conflictC
=
0
;
vec
<
Lit
>
learnt_clause
,
selectors
;
unsigned
int
nblevels
,
szWoutSelectors
;
bool
blocked
=
false
;
starts
++
;
for
(;;){
CRef
confl
=
propagate
();
if
(
confl
!=
CRef_Undef
){
// CONFLICT
conflicts
++
;
conflictC
++
;
conflictsRestarts
++
;
if
(
conflicts
%
5000
==
0
&&
var_decay
<
0.95
)
var_decay
+=
0.01
;
if
(
verbosity
>=
1
&&
conflicts
%
verbEveryConflicts
==
0
){
printf
(
"c | %8d %7d %5d | %7d %8d %8d | %5d %8d %6d %8d | %6.3f %% |
\n
"
,
(
int
)
starts
,(
int
)
nbstopsrestarts
,
(
int
)(
conflicts
/
starts
),
(
int
)
dec_vars
-
(
trail_lim
.
size
()
==
0
?
trail
.
size
()
:
trail_lim
[
0
]),
nClauses
(),
(
int
)
clauses_literals
,
(
int
)
nbReduceDB
,
nLearnts
(),
(
int
)
nbDL2
,(
int
)
nbRemovedClauses
,
progressEstimate
()
*
100
);
}
if
(
decisionLevel
()
==
0
)
{
return
l_False
;
}
trailQueue
.
push
(
trail
.
size
());
// BLOCK RESTART (CP 2012 paper)
if
(
conflictsRestarts
>
LOWER_BOUND_FOR_BLOCKING_RESTART
&&
lbdQueue
.
isvalid
()
&&
trail
.
size
()
>
R
*
trailQueue
.
getavg
())
{
lbdQueue
.
fastclear
();
nbstopsrestarts
++
;
if
(
!
blocked
)
{
lastblockatrestart
=
starts
;
nbstopsrestartssame
++
;
blocked
=
true
;}
}
learnt_clause
.
clear
();
selectors
.
clear
();
analyze
(
confl
,
learnt_clause
,
selectors
,
backtrack_level
,
nblevels
,
szWoutSelectors
);
lbdQueue
.
push
(
nblevels
);
sumLBD
+=
nblevels
;
cancelUntil
(
backtrack_level
);
if
(
certifiedUNSAT
)
{
for
(
int
i
=
0
;
i
<
learnt_clause
.
size
();
i
++
)
fprintf
(
certifiedOutput
,
"%i "
,
(
var
(
learnt_clause
[
i
])
+
1
)
*
(
-2
*
sign
(
learnt_clause
[
i
])
+
1
)
);
fprintf
(
certifiedOutput
,
"0
\n
"
);
}
if
(
learnt_clause
.
size
()
==
1
){
uncheckedEnqueue
(
learnt_clause
[
0
]);
nbUn
++
;
}
else
{
CRef
cr
=
ca
.
alloc
(
learnt_clause
,
true
);
ca
[
cr
].
setLBD
(
nblevels
);
ca
[
cr
].
setSizeWithoutSelectors
(
szWoutSelectors
);
if
(
nblevels
<=
2
)
nbDL2
++
;
// stats
if
(
ca
[
cr
].
size
()
==
2
)
nbBin
++
;
// stats
learnts
.
push
(
cr
);
attachClause
(
cr
);
claBumpActivity
(
ca
[
cr
]);
uncheckedEnqueue
(
learnt_clause
[
0
],
cr
);
}
varDecayActivity
();
claDecayActivity
();
}
else
{
// Our dynamic restart, see the SAT09 competition compagnion paper
if
(
(
conflictsRestarts
&&
lbdQueue
.
isvalid
()
&&
lbdQueue
.
getavg
()
*
K
>
sumLBD
/
conflictsRestarts
)
||
(
pstop
&&
*
pstop
)
)
{
lbdQueue
.
fastclear
();
progress_estimate
=
progressEstimate
();
int
bt
=
0
;
if
(
incremental
)
{
// DO NOT BACKTRACK UNTIL 0.. USELESS
bt
=
(
decisionLevel
()
<
assumptions
.
size
())
?
decisionLevel
()
:
assumptions
.
size
();
}
cancelUntil
(
bt
);
return
l_Undef
;
}
// Simplify the set of problem clauses:
if
(
decisionLevel
()
==
0
&&
!
simplify
())
{
return
l_False
;
}
// Perform clause database reduction !
if
(
conflicts
>=
curRestart
*
nbclausesbeforereduce
)
{
assert
(
learnts
.
size
()
>
0
);
curRestart
=
(
conflicts
/
nbclausesbeforereduce
)
+
1
;
reduceDB
();
nbclausesbeforereduce
+=
incReduceDB
;
}
Lit
next
=
lit_Undef
;
while
(
decisionLevel
()
<
assumptions
.
size
()){
// Perform user provided assumption:
Lit
p
=
assumptions
[
decisionLevel
()];
if
(
value
(
p
)
==
l_True
){
// Dummy decision level:
newDecisionLevel
();
}
else
if
(
value
(
p
)
==
l_False
){
analyzeFinal
(
~
p
,
conflict
);
return
l_False
;
}
else
{
next
=
p
;
break
;
}
}
if
(
next
==
lit_Undef
){
// New variable decision:
decisions
++
;
next
=
pickBranchLit
();
if
(
next
==
lit_Undef
){
//printf("c last restart ## conflicts : %d %d \n",conflictC,decisionLevel());
// Model found:
return
l_True
;
}
}
// Increase decision level and enqueue 'next'
newDecisionLevel
();
uncheckedEnqueue
(
next
);
}
}
}
double
Solver::progressEstimate
()
const
{
double
progress
=
0
;
double
F
=
1.0
/
nVars
();
for
(
int
i
=
0
;
i
<=
decisionLevel
();
i
++
){
int
beg
=
i
==
0
?
0
:
trail_lim
[
i
-
1
];
int
end
=
i
==
decisionLevel
()
?
trail
.
size
()
:
trail_lim
[
i
];
progress
+=
pow
(
F
,
i
)
*
(
end
-
beg
);
}
return
progress
/
nVars
();
}
void
Solver::printIncrementalStats
()
{
printf
(
"c---------- Glucose Stats -------------------------
\n
"
);
printf
(
"c restarts : %ld
\n
"
,
starts
);
printf
(
"c nb ReduceDB : %ld
\n
"
,
nbReduceDB
);
printf
(
"c nb removed Clauses : %ld
\n
"
,
nbRemovedClauses
);
printf
(
"c nb learnts DL2 : %ld
\n
"
,
nbDL2
);
printf
(
"c nb learnts size 2 : %ld
\n
"
,
nbBin
);
printf
(
"c nb learnts size 1 : %ld
\n
"
,
nbUn
);
printf
(
"c conflicts : %ld
\n
"
,
conflicts
);
printf
(
"c decisions : %ld
\n
"
,
decisions
);
printf
(
"c propagations : %ld
\n
"
,
propagations
);
printf
(
"c SAT Calls : %d in %g seconds
\n
"
,
nbSatCalls
,
totalTime4Sat
);
printf
(
"c UNSAT Calls : %d in %g seconds
\n
"
,
nbUnsatCalls
,
totalTime4Unsat
);
printf
(
"c--------------------------------------------------
\n
"
);
}
// NOTE: assumptions passed in member-variable 'assumptions'.
lbool
Solver::solve_
()
{
if
(
incremental
&&
certifiedUNSAT
)
{
printf
(
"Can not use incremental and certified unsat in the same time
\n
"
);
exit
(
-1
);
}
model
.
clear
();
conflict
.
clear
();
if
(
!
ok
)
return
l_False
;
double
curTime
=
cpuTime
();
solves
++
;
lbool
status
=
l_Undef
;
if
(
!
incremental
&&
verbosity
>=
1
)
{
printf
(
"c ========================================[ MAGIC CONSTANTS ]==============================================
\n
"
);
printf
(
"c | Constants are supposed to work well together :-) |
\n
"
);
printf
(
"c | however, if you find better choices, please let us known... |
\n
"
);
printf
(
"c |-------------------------------------------------------------------------------------------------------|
\n
"
);
printf
(
"c | | | |
\n
"
);
printf
(
"c | - Restarts: | - Reduce Clause DB: | - Minimize Asserting: |
\n
"
);
printf
(
"c | * LBD Queue : %6d | * First : %6d | * size < %3d |
\n
"
,
lbdQueue
.
maxSize
(),
nbclausesbeforereduce
,
lbSizeMinimizingClause
);
printf
(
"c | * Trail Queue : %6d | * Inc : %6d | * lbd < %3d |
\n
"
,
trailQueue
.
maxSize
(),
incReduceDB
,
lbLBDMinimizingClause
);
printf
(
"c | * K : %6.2f | * Special : %6d | |
\n
"
,
K
,
specialIncReduceDB
);
printf
(
"c | * R : %6.2f | * Protected : (lbd)< %2d | |
\n
"
,
R
,
lbLBDFrozenClause
);
printf
(
"c | | | |
\n
"
);
printf
(
"c ==================================[ Search Statistics (every %6d conflicts) ]=========================
\n
"
,
verbEveryConflicts
);
printf
(
"c | |
\n
"
);
printf
(
"c | RESTARTS | ORIGINAL | LEARNT | Progress |
\n
"
);
printf
(
"c | NB Blocked Avg Cfc | Vars Clauses Literals | Red Learnts LBD2 Removed | |
\n
"
);
printf
(
"c =========================================================================================================
\n
"
);
}
// Search:
int
curr_restarts
=
0
;
while
(
status
==
l_Undef
){
status
=
search
(
0
);
// the parameter is useless in glucose, kept to allow modifications
if
(
!
withinBudget
()
||
terminate_search_early
||
(
pstop
&&
*
pstop
))
break
;
if
(
nRuntimeLimit
&&
Abc_Clock
()
>
nRuntimeLimit
)
break
;
curr_restarts
++
;
}
if
(
!
incremental
&&
verbosity
>=
1
)
printf
(
"c =========================================================================================================
\n
"
);
if
(
certifiedUNSAT
){
// Want certified output
if
(
status
==
l_False
)
fprintf
(
certifiedOutput
,
"0
\n
"
);
fclose
(
certifiedOutput
);
}
if
(
status
==
l_True
){
// Extend & copy model:
model
.
growTo
(
nVars
());
for
(
int
i
=
0
;
i
<
nVars
();
i
++
)
model
[
i
]
=
value
(
i
);
}
else
if
(
status
==
l_False
&&
conflict
.
size
()
==
0
)
ok
=
false
;
cancelUntil
(
0
);
double
finalTime
=
cpuTime
();
if
(
status
==
l_True
)
{
nbSatCalls
++
;
totalTime4Sat
+=
(
finalTime
-
curTime
);
}
if
(
status
==
l_False
)
{
nbUnsatCalls
++
;
totalTime4Unsat
+=
(
finalTime
-
curTime
);
}
// ABC callback
if
(
pCnfFunc
&&
!
terminate_search_early
)
{
// hack to avoid calling callback twise if the solver was terminated early
int
*
pCex
=
NULL
;
int
message
=
(
status
==
l_True
?
1
:
status
==
l_False
?
0
:
-1
);
if
(
status
==
l_True
)
{
pCex
=
new
int
[
nVars
()];
for
(
int
i
=
0
;
i
<
nVars
();
i
++
)
pCex
[
i
]
=
(
model
[
i
]
==
l_True
);
}
int
callback_result
=
pCnfFunc
(
pCnfMan
,
message
,
pCex
);
assert
(
callback_result
==
0
);
}
else
if
(
pCnfFunc
)
terminate_search_early
=
false
;
// for next run
return
status
;
}
//=================================================================================================
// Writing CNF to DIMACS:
//
// FIXME: this needs to be rewritten completely.
static
Var
mapVar
(
Var
x
,
vec
<
Var
>&
map
,
Var
&
max
)
{
if
(
map
.
size
()
<=
x
||
map
[
x
]
==
-1
){
map
.
growTo
(
x
+
1
,
-1
);
map
[
x
]
=
max
++
;
}
return
map
[
x
];
}
void
Solver::toDimacs
(
FILE
*
f
,
Clause
&
c
,
vec
<
Var
>&
map
,
Var
&
max
)
{
if
(
satisfied
(
c
))
return
;
for
(
int
i
=
0
;
i
<
c
.
size
();
i
++
)
if
(
value
(
c
[
i
])
!=
l_False
)
fprintf
(
f
,
"%s%d "
,
sign
(
c
[
i
])
?
"-"
:
""
,
mapVar
(
var
(
c
[
i
]),
map
,
max
)
+
1
);
fprintf
(
f
,
"0
\n
"
);
}
void
Solver::toDimacs
(
const
char
*
file
,
const
vec
<
Lit
>&
assumps
)
{
FILE
*
f
=
fopen
(
file
,
"wr"
);
if
(
f
==
NULL
)
fprintf
(
stderr
,
"could not open file %s
\n
"
,
file
),
exit
(
1
);
toDimacs
(
f
,
assumps
);
fclose
(
f
);
}
void
Solver::toDimacs
(
FILE
*
f
,
const
vec
<
Lit
>&
assumps
)
{
// Handle case when solver is in contradictory state:
if
(
!
ok
){
fprintf
(
f
,
"p cnf 1 2
\n
1 0
\n
-1 0
\n
"
);
return
;
}
vec
<
Var
>
map
;
Var
max
=
0
;
// Cannot use removeClauses here because it is not safe
// to deallocate them at this point. Could be improved.
int
i
,
cnt
=
0
;
for
(
i
=
0
;
i
<
clauses
.
size
();
i
++
)
if
(
!
satisfied
(
ca
[
clauses
[
i
]]))
cnt
++
;
for
(
i
=
0
;
i
<
clauses
.
size
();
i
++
)
if
(
!
satisfied
(
ca
[
clauses
[
i
]])){
Clause
&
c
=
ca
[
clauses
[
i
]];
for
(
int
j
=
0
;
j
<
c
.
size
();
j
++
)
if
(
value
(
c
[
j
])
!=
l_False
)
mapVar
(
var
(
c
[
j
]),
map
,
max
);
}
// Assumptions are added as unit clauses:
cnt
+=
assumptions
.
size
();
fprintf
(
f
,
"p cnf %d %d
\n
"
,
max
,
cnt
);
for
(
i
=
0
;
i
<
assumptions
.
size
();
i
++
){
assert
(
value
(
assumptions
[
i
])
!=
l_False
);
fprintf
(
f
,
"%s%d 0
\n
"
,
sign
(
assumptions
[
i
])
?
"-"
:
""
,
mapVar
(
var
(
assumptions
[
i
]),
map
,
max
)
+
1
);
}
for
(
i
=
0
;
i
<
clauses
.
size
();
i
++
)
toDimacs
(
f
,
ca
[
clauses
[
i
]],
map
,
max
);
if
(
verbosity
>
0
)
printf
(
"Wrote %d clauses with %d variables.
\n
"
,
cnt
,
max
);
}
//=================================================================================================
// Garbage Collection methods:
void
Solver::relocAll
(
ClauseAllocator
&
to
)
{
int
v
,
s
,
i
,
j
;
// All watchers:
//
// for (int i = 0; i < watches.size(); i++)
watches
.
cleanAll
();
watchesBin
.
cleanAll
();
for
(
v
=
0
;
v
<
nVars
();
v
++
)
for
(
s
=
0
;
s
<
2
;
s
++
){
Lit
p
=
mkLit
(
v
,
s
!=
0
);
// printf(" >>> RELOCING: %s%d\n", sign(p)?"-":"", var(p)+1);
vec
<
Watcher
>&
ws
=
watches
[
p
];
for
(
j
=
0
;
j
<
ws
.
size
();
j
++
)
ca
.
reloc
(
ws
[
j
].
cref
,
to
);
vec
<
Watcher
>&
ws2
=
watchesBin
[
p
];
for
(
j
=
0
;
j
<
ws2
.
size
();
j
++
)
ca
.
reloc
(
ws2
[
j
].
cref
,
to
);
}
// All reasons:
//
for
(
i
=
0
;
i
<
trail
.
size
();
i
++
){
Var
v
=
var
(
trail
[
i
]);
if
(
reason
(
v
)
!=
CRef_Undef
&&
(
ca
[
reason
(
v
)].
reloced
()
||
locked
(
ca
[
reason
(
v
)])))
ca
.
reloc
(
vardata
[
v
].
reason
,
to
);
}
// All learnt:
//
for
(
i
=
0
;
i
<
learnts
.
size
();
i
++
)
ca
.
reloc
(
learnts
[
i
],
to
);
// All original:
//
for
(
i
=
0
;
i
<
clauses
.
size
();
i
++
)
ca
.
reloc
(
clauses
[
i
],
to
);
}
void
Solver::garbageCollect
()
{
// Initialize the next region to a size corresponding to the estimated utilization degree. This
// is not precise but should avoid some unnecessary reallocations for the new region:
ClauseAllocator
to
(
ca
.
size
()
-
ca
.
wasted
());
relocAll
(
to
);
if
(
verbosity
>=
2
)
printf
(
"| Garbage collection: %12d bytes => %12d bytes |
\n
"
,
ca
.
size
()
*
ClauseAllocator
::
Unit_Size
,
to
.
size
()
*
ClauseAllocator
::
Unit_Size
);
to
.
moveTo
(
ca
);
}
void
Solver::reset
()
{
// Reset everything
ok
=
true
;
K
=
(
double
)
opt_K
;
R
=
(
double
)
opt_R
;
firstReduceDB
=
opt_first_reduce_db
;
var_decay
=
(
double
)
opt_var_decay
;
//max_var_decay = opt_max_var_decay;
solves
=
starts
=
decisions
=
propagations
=
conflicts
=
conflictsRestarts
=
0
;
curRestart
=
1
;
cla_inc
=
var_inc
=
1
;
watches
.
clear
(
false
);
// We don't free the memory, new calls should be of the same size order.
watchesBin
.
clear
(
false
);
//unaryWatches.clear(false);
qhead
=
0
;
simpDB_assigns
=
-1
;
simpDB_props
=
0
;
order_heap
.
clear
(
false
);
progress_estimate
=
0
;
//lastLearntClause = CRef_Undef;
conflict_budget
=
-1
;
propagation_budget
=
-1
;
nbVarsInitialFormula
=
INT32_MAX
;
totalTime4Sat
=
0.
;
totalTime4Unsat
=
0.
;
nbSatCalls
=
nbUnsatCalls
=
0
;
MYFLAG
=
0
;
lbdQueue
.
clear
(
false
);
lbdQueue
.
initSize
(
sizeLBDQueue
);
trailQueue
.
clear
(
false
);
trailQueue
.
initSize
(
sizeTrailQueue
);
sumLBD
=
0
;
nbclausesbeforereduce
=
firstReduceDB
;
//stats.clear();
//stats.growTo(coreStatsSize, 0);
clauses
.
clear
(
false
);
learnts
.
clear
(
false
);
//permanentLearnts.clear(false);
//unaryWatchedClauses.clear(false);
model
.
clear
(
false
);
conflict
.
clear
(
false
);
activity
.
clear
(
false
);
assigns
.
clear
(
false
);
polarity
.
clear
(
false
);
//forceUNSAT.clear(false);
decision
.
clear
(
false
);
trail
.
clear
(
false
);
nbpos
.
clear
(
false
);
trail_lim
.
clear
(
false
);
vardata
.
clear
(
false
);
assumptions
.
clear
(
false
);
permDiff
.
clear
(
false
);
lastDecisionLevel
.
clear
(
false
);
ca
.
clear
();
seen
.
clear
(
false
);
analyze_stack
.
clear
(
false
);
analyze_toclear
.
clear
(
false
);
add_tmp
.
clear
(
false
);
assumptionPositions
.
clear
(
false
);
initialPositions
.
clear
(
false
);
}
ABC_NAMESPACE_IMPL_END
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Tue, Oct 27, 4:29 PM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
407459
Default Alt Text
Glucose.cpp (48 KB)
Attached To
Mode
R272 SoC_NEM_Synthesis
Attached
Detach File
Event Timeline