Skip to content

Commit ad5e726

Browse files
committed
feat!: Monotone trait for encodings
and requiring it for solution-improving search
1 parent 8392fec commit ad5e726

File tree

6 files changed

+38
-7
lines changed

6 files changed

+38
-7
lines changed

src/algs/maxsat.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use std::marker::PhantomData;
88

99
use crate::{
10-
encodings::pb,
10+
encodings::{pb, Monotone},
1111
instances::BasicVarManager,
1212
solvers::{SolveIncremental, SolveStats, SolverResult},
1313
types::{Assignment, Lit, TernaryVal},
@@ -57,7 +57,7 @@ pub struct SolutionImprovingSearch<Solver, PbEnc> {
5757
impl<Solver, PbEnc> Solve for SolutionImprovingSearch<Solver, PbEnc>
5858
where
5959
Solver: SolveIncremental + SolveStats,
60-
PbEnc: FromIterator<(Lit, usize)> + pb::BoundUpperIncremental,
60+
PbEnc: FromIterator<(Lit, usize)> + pb::BoundUpperIncremental + Monotone,
6161
{
6262
type Solver = Solver;
6363

src/encodings.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ pub enum ConstraintEncodingError {
6565
OutOfMemory(#[from] crate::OutOfMemory),
6666
}
6767

68+
/// Marker trait for "monotone" incremental encodings, i.e., encodings for which enforcing `sum <=
69+
/// k` (as hard clauses) does not conflict with enforcing `sum <= k - x` later.
70+
///
71+
/// The [`pb::DynamicPolyWatchdog`] is a notable exception to this, because of its tare variables.
72+
pub trait Monotone {}
73+
6874
/// Trait for encodings that track statistics.
6975
pub trait EncodeStats {
7076
/// Gets the number of clauses in the encoding

src/encodings/card/totalizer.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{cmp, ops::RangeBounds};
88
use crate::{
99
encodings::{
1010
nodedb::{NodeById, NodeCon, NodeId, NodeLike},
11-
totdb, CollectClauses, EncodeStats, EnforceError, NotEncoded,
11+
totdb, CollectClauses, EncodeStats, EnforceError, Monotone, NotEncoded,
1212
},
1313
instances::ManageVars,
1414
types::Lit,
@@ -335,6 +335,8 @@ impl BoundBoth for Totalizer {
335335

336336
impl BoundBothIncremental for Totalizer {}
337337

338+
impl Monotone for Totalizer {}
339+
338340
impl EncodeStats for Totalizer {
339341
fn n_clauses(&self) -> usize {
340342
self.n_clauses

src/encodings/pb/adder.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::collections::VecDeque;
1919

2020
use crate::{
2121
clause,
22-
encodings::{CollectClauses, EncodeStats, EnforceError},
22+
encodings::{CollectClauses, EncodeStats, EnforceError, Monotone},
2323
instances::ManageVars,
2424
types::{Clause, Lit, RsHashMap},
2525
OutOfMemory,
@@ -420,6 +420,8 @@ impl EncodeIncremental for BinaryAdder {
420420
}
421421
}
422422

423+
impl Monotone for BinaryAdder {}
424+
423425
impl EncodeStats for BinaryAdder {
424426
fn n_clauses(&self) -> usize {
425427
self.n_clauses

src/encodings/pb/gte.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::ops::RangeBounds;
88
use crate::{
99
encodings::{
1010
nodedb::{NodeById, NodeCon, NodeLike},
11-
totdb, CollectClauses, EncodeStats, EnforceError,
11+
totdb, CollectClauses, EncodeStats, EnforceError, Monotone,
1212
},
1313
instances::ManageVars,
1414
types::{Lit, RsHashMap},
@@ -326,6 +326,8 @@ impl BoundUpperIncremental for GeneralizedTotalizer {
326326
}
327327
}
328328

329+
impl Monotone for GeneralizedTotalizer {}
330+
329331
impl EncodeStats for GeneralizedTotalizer {
330332
fn n_clauses(&self) -> usize {
331333
self.n_clauses

tests/maxsat.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustsat::{algs::maxsat, encodings::pb, instances::OptInstance};
22

33
#[test]
4-
fn sis_small() {
4+
fn sis_small_gte() {
55
type Alg =
66
maxsat::SolutionImprovingSearch<rustsat_minisat::core::Minisat, pb::GeneralizedTotalizer>;
77
let inst: OptInstance = OptInstance::from_dimacs_path("./data/inc-sis-fails.wcnf").unwrap();
@@ -11,7 +11,7 @@ fn sis_small() {
1111
}
1212

1313
#[test]
14-
fn sis() {
14+
fn sis_gte() {
1515
type Alg =
1616
maxsat::SolutionImprovingSearch<rustsat_minisat::core::Minisat, pb::GeneralizedTotalizer>;
1717
let inst: OptInstance =
@@ -20,3 +20,22 @@ fn sis() {
2020
dbg!(&sol);
2121
assert!(matches!(sol, Some((_, 61169))));
2222
}
23+
24+
#[test]
25+
fn sis_small_adder() {
26+
type Alg = maxsat::SolutionImprovingSearch<rustsat_minisat::core::Minisat, pb::BinaryAdder>;
27+
let inst: OptInstance = OptInstance::from_dimacs_path("./data/inc-sis-fails.wcnf").unwrap();
28+
let sol = inst.solve_maxsat::<Alg>();
29+
dbg!(&sol);
30+
assert!(matches!(sol, Some((_, 8632))));
31+
}
32+
33+
#[test]
34+
fn sis_adder() {
35+
type Alg = maxsat::SolutionImprovingSearch<rustsat_minisat::core::Minisat, pb::BinaryAdder>;
36+
let inst: OptInstance =
37+
OptInstance::from_dimacs_path("./data/auctions_wt-cat_sched_60_70_0003.txt.wcnf").unwrap();
38+
let sol = inst.solve_maxsat::<Alg>();
39+
dbg!(&sol);
40+
assert!(matches!(sol, Some((_, 61169))));
41+
}

0 commit comments

Comments
 (0)