Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SLS #192

Closed
wants to merge 29 commits into from
Closed

SLS #192

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e51c883
the initial implementation of SLS
shnarazk Oct 11, 2022
1f52bdb
add new feature 'stochastic_local_search'
shnarazk Oct 11, 2022
5615de3
wiring
shnarazk Oct 11, 2022
9f9e2c9
ditto
shnarazk Oct 11, 2022
d10a3a2
a snapshot
shnarazk Oct 12, 2022
3b9dc5d
Better results
shnarazk Oct 13, 2022
2d66442
a snapshot
shnarazk Oct 14, 2022
9b68d12
revert a meaningless change
shnarazk Oct 16, 2022
ab87abc
Cargo.toml: explain each of features
shnarazk Oct 16, 2022
528c5da
Cargo.toml: reorganize default features
shnarazk Oct 16, 2022
e0d769d
src/cdb/sls.rs: revised
shnarazk Oct 16, 2022
e375e2e
(search) reset StageManager whenever a new assertion is found
shnarazk Oct 16, 2022
f878f3f
fix typos
shnarazk Oct 17, 2022
2bc49bd
revise progress report
shnarazk Oct 17, 2022
6021477
modified: src/cdb/sls.rs
shnarazk Oct 17, 2022
0469c72
(search) revise the stocastic_local_search invocation condition
shnarazk Oct 17, 2022
c81c11d
Add AssignIF::best_phases_invalid
shnarazk Oct 18, 2022
8e78975
a snapshot
shnarazk Oct 18, 2022
3a5e0d9
(stochastic_local_search) shrink a pseudo random number range
shnarazk Oct 18, 2022
7e3ebf6
A snapshot
shnarazk Oct 18, 2022
09a1739
make stochastic_local_search essential
shnarazk Oct 19, 2022
a550233
(reduce) change reduction parameters to keep much clauses if the tota…
shnarazk Oct 19, 2022
cfdc7aa
(reduce) memory-pressure
shnarazk Oct 22, 2022
29e8260
(search) a snapshot
shnarazk Oct 22, 2022
a689e42
change the definition of a 'cylcle' from an increasing sequence to a …
shnarazk Oct 22, 2022
392801e
Fix calculation bugs on segment number and stage span
shnarazk Oct 22, 2022
0b5242a
(search) fix a calculation bug on stage index in cycle
shnarazk Oct 22, 2022
df18bd1
fix a compilation error without 'stochastic_local_search'
shnarazk Oct 22, 2022
dbf2e9b
(reduce) a parameter tuning
shnarazk Oct 22, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 53 additions & 38 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "splr"
version = "0.17.0-alpha.2"
version = "0.17.0-alpha.3"
authors = ["Narazaki Shuji <shujinarazaki@protonmail.com>"]
description = "A modern CDCL SAT solver in Rust"
edition = "2021"
Expand All @@ -17,49 +17,64 @@ bitflags = "^1.3"

[features]
default = [
# "boundary_check", # for DEBUG
# "bi_clause_completion", # increase memory pressure
# "no_clause_elimination",
# "clause_rewarding",
"clause_vivification",
"dynamic_restart_threshold",
### Essential
# "incremental_solver",
"LRB_rewarding",
# "maintain_watch_cache", # for DEBUG
"reason_side_rewarding",
"unsafe_access",
"trail_saving",

### heuristics
# "bi_clause_completion",
# "clause_rewarding",
"dynamic_restart_threshold",
"rephase",
# "reward_annealing", # for big problems since 0.17(need to evalate with larger timeout)
# "reward_annealing",
"stochastic_local_search",
# "suppress_reason_chain",
"trail_saving",
"unsafe_access"

### proceccor
# "no_clause_elimination",
"clause_vivification",

### for DEBUG
# "boundary_check",
# "maintain_watch_cache",
]
assign_rate = [] # for debug and study
best_phases_tracking = [] # save the best-so-far assignment, used by 'rephase'
bi_clause_completion = [] # increase memory pressure
boundary_check = [] # for debug
chrono_BT = [] # NOT WORK
no_clause_elimination = [] # pre(in)-processor setting
clause_rewarding = [] # clauses have activities w/ decay rate
clause_vivification = [] # pre(in)-processor setting
debug_propagation = [] # for debug
dynamic_restart_threshold = [] # control restart spans like Glucose
EMA_calibration = [] # each exponential moving average has a calbration value
EVSIDS = [] # Eponential Variable State Independent Decaying Sum
incremental_solver = [ # for all solution SAT sover
"no_clause_elimination"
]
just_used = [] # Var and clause have 'just_used' flags
LRB_rewarding = [] # Vearning Rate Based rewarding, a new var activity criteria
maintain_watch_cache = [] # for DEBUG
no_IO = [] # to embed Splr into non-std environments
reason_side_rewarding = [] # an idea used in Learning-rate based rewarding
rephase = [ # search around the best-so-far candidate repeatedly
"best_phases_tracking"
]
reward_annealing = [] # use bigger and smaller decay rates cycliclly
stochastic_local_search = [ # since 0.17
"reward_annealing"
]
assign_rate = []
best_phases_tracking = []
bi_clause_completion = []
boundary_check = []
chrono_BT = []
no_clause_elimination = []
clause_rewarding = []
clause_vivification = []
debug_propagation = []
dynamic_restart_threshold = []
EMA_calibration = []
EVSIDS = []
incremental_solver = ["no_clause_elimination"]
just_used = []
LRB_rewarding = []
maintain_watch_cache = []
no_IO = []
reason_side_rewarding = []
rephase = ["best_phases_tracking"]
reward_annealing = []
support_user_assumption = []
suppress_reason_chain = []
trace_analysis = []
trace_elimination = []
trace_equivalency = []
trail_saving = []
unsafe_access = []
support_user_assumption = [] # NOT WORK (defined in Glucose)
suppress_reason_chain = [] # make direct links between a dicision var and its implications
trace_analysis = [] # for debug
trace_elimination = [] # for debug
trace_equivalency = [] # for debug
trail_saving = [] # reduce propagation cost by reusing propagation chain
unsafe_access = [] # access elements of vectors without boundary checking

[profile.release]
lto = "fat"
Expand Down
2 changes: 2 additions & 0 deletions src/assign/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ pub trait AssignIF:
/// return a reference to `level`.
fn level_ref(&self) -> &[DecisionLevel];
fn best_assigned(&mut self) -> Option<usize>;
/// return true if no best_phases
fn best_phases_invalid(&self) -> bool;
/// inject assignments for eliminated vars.
fn extend_model(&mut self, c: &mut impl ClauseDBIF) -> Vec<Option<bool>>;
/// return `true` if the set of literals is satisfiable under the current assignment.
Expand Down
43 changes: 43 additions & 0 deletions src/assign/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use super::property;
use {
super::{AssignStack, VarHeapIF},
crate::types::*,
std::collections::HashMap,
};

/// ```ignore
Expand All @@ -26,6 +27,10 @@ macro_rules! var_assign {

/// API for var selection, depending on an internal heap.
pub trait VarSelectIF {
/// return best phases
fn best_phases_ref(&mut self, default_value: Option<bool>) -> HashMap<VarId, bool>;
/// force an assignment obtained by SLS
fn override_rephasing_target(&mut self, assignment: &HashMap<VarId, bool>) -> usize;
#[cfg(feature = "rephase")]
/// select rephasing target
fn select_rephasing_target(&mut self);
Expand All @@ -41,6 +46,44 @@ pub trait VarSelectIF {
}

impl VarSelectIF for AssignStack {
fn best_phases_ref(&mut self, default_value: Option<bool>) -> HashMap<VarId, bool> {
self.var
.iter()
.enumerate()
.filter_map(|(vi, v)| {
if self.level[vi] == self.root_level || self.var[vi].is(FlagVar::ELIMINATED) {
default_value.map(|b| (vi, b))
} else {
Some((
vi,
self.best_phases.get(&vi).map_or(
self.assign[vi].unwrap_or_else(|| v.is(FlagVar::PHASE)),
|(b, _)| *b,
),
))
}
})
.collect::<HashMap<VarId, bool>>()
}
fn override_rephasing_target(&mut self, assignment: &HashMap<VarId, bool>) -> usize {
let mut num_flipped = 0;
for (vi, b) in assignment.iter() {
// let v = &mut self.var[*vi];
// if v.is(FlagVar::PHASE) != *b {
// num_flipped += 1;
// v.set(FlagVar::PHASE, *b);
// // v.reward *= self.activity_decay;
// // v.reward += self.activity_anti_decay;
// // self.update_heap(*vi);
// }
if !self.best_phases.get(vi).map_or(false, |(p, _)| *p == *b) {
num_flipped += 1;
self.best_phases.insert(*vi, (*b, AssignReason::None));
}
}
// self.num_best_assign = self.num_asserted_vars + self.num_eliminated_vars;
num_flipped
}
#[cfg(feature = "rephase")]
fn select_rephasing_target(&mut self) {
if self.best_phases.is_empty() {
Expand Down
3 changes: 3 additions & 0 deletions src/assign/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ impl AssignIF for AssignStack {
fn best_assigned(&mut self) -> Option<usize> {
(self.build_best_at == self.num_propagation).then_some(self.num_vars - self.num_best_assign)
}
fn best_phases_invalid(&self) -> bool {
self.best_phases.is_empty()
}
#[allow(unused_variables)]
fn extend_model(&mut self, cdb: &mut impl ClauseDBIF) -> Vec<Option<bool>> {
let lits = &self.eliminated;
Expand Down
4 changes: 4 additions & 0 deletions src/cdb/activity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ impl ActivityIF<ClauseId> for ClauseDB {
fn update_activity_tick(&mut self) {
self.tick += 1;
}
fn update_activity_decay(&mut self, decay: f64) {
self.activity_decay = decay;
self.activity_anti_decay = 1.0 - decay;
}
}

impl Clause {
Expand Down
10 changes: 8 additions & 2 deletions src/cdb/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ impl Default for ClauseDB {
num_reduction: 0,
num_reregistration: 0,
lb_entanglement: Ema2::new(1_000).with_slow(80_000).with_value(2.0),
last_reduction_threshold: 0,
eliminated_permanent: Vec::new(),
}
}
Expand Down Expand Up @@ -1022,16 +1023,21 @@ impl ClauseDBIF for ClauseDB {
}
perm.sort();
// Worse half of `perm` should be discarded now. But many people thought
// there're exception. Since this is the pre-stage of clause vivification,
// there're exceptions. Since this is the pre-stage of clause vivification,
// we want keep usefull clauses as many as possible.
// Therefore I save the clauses which will become vivification targets.
let thr = (self.lb_entanglement.get_slow() + 1.0).min(self.lbd.get_fast().max(5.0)) as u16;
// And since the current Splr adopts stage-based GC policy, I drop this simple halve'em if doubled,
// based on memomy pressure and clause sizes used in conflict analysis.
let entanglement = 1.75 * (self.lb_entanglement.get_slow() + self.lbd.get_slow()).powf(0.5);
let memory_pressure = 2000.0 * (self.num_learnt as f64).powf(-0.5);
let thr = (entanglement + memory_pressure).min(entanglement) as u16;
for i in &perm[keep..] {
let c = &self.clause[i.to()];
if !c.is_vivify_target() || thr < c.rank {
self.remove_clause(ClauseId::from(i.to()));
}
}
self.last_reduction_threshold = thr as usize;
}
fn reset(&mut self) {
debug_assert!(1 < self.clause.len());
Expand Down
13 changes: 11 additions & 2 deletions src/cdb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ mod clause;
mod db;
/// EMA
mod ema;
/// methods for Stochastic Local Search
mod sls;
/// methods for UNSAT certification
mod unsat_certificate;
/// implementation of clause vivification
Expand All @@ -21,9 +23,11 @@ pub use self::{
binary::{BinaryLinkDB, BinaryLinkList},
cid::ClauseIdIF,
property::*,
sls::StochasticLocalSearchIF,
unsat_certificate::CertificationStore,
vivify::VivifyIF,
};

use {
self::ema::ProgressLBD,
crate::{assign::AssignIF, types::*},
Expand Down Expand Up @@ -285,7 +289,9 @@ pub struct ClauseDB {
num_reregistration: usize,
/// Literal Block Entanglement
/// EMA of LBD of clauses used in conflict analysis (dependency graph)
pub lb_entanglement: Ema2,
lb_entanglement: Ema2,
/// the decision level used in th last invocation of `reduce`
last_reduction_threshold: usize,

//
//## incremental solving
Expand All @@ -307,10 +313,11 @@ pub mod property {
NumLearnt,
NumReduction,
NumReRegistration,
ReductionThreshold,
Timestamp,
}

pub const USIZES: [Tusize; 9] = [
pub const USIZES: [Tusize; 10] = [
Tusize::NumBiClause,
Tusize::NumBiClauseCompletion,
Tusize::NumBiLearnt,
Expand All @@ -319,6 +326,7 @@ pub mod property {
Tusize::NumLearnt,
Tusize::NumReduction,
Tusize::NumReRegistration,
Tusize::ReductionThreshold,
Tusize::Timestamp,
];

Expand All @@ -334,6 +342,7 @@ pub mod property {
Tusize::NumLearnt => self.num_learnt,
Tusize::NumReduction => self.num_reduction,
Tusize::NumReRegistration => self.num_reregistration,
Tusize::ReductionThreshold => self.last_reduction_threshold,

#[cfg(feature = "clause_rewarding")]
Tusize::Timestamp => self.tick,
Expand Down
Loading