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 package org.sat4j.minisat.constraints;
27
28 import java.math.BigInteger;
29
30 import org.sat4j.minisat.constraints.card.AtLeast;
31 import org.sat4j.minisat.constraints.cnf.Lits;
32 import org.sat4j.minisat.core.Constr;
33 import org.sat4j.minisat.core.ILits;
34 import org.sat4j.specs.ContradictionException;
35 import org.sat4j.specs.IVec;
36 import org.sat4j.specs.IVecInt;
37
38
39
40
41
42 @SuppressWarnings("PMD")
43 public abstract class AbstractCardinalityDataStructure extends
44 AbstractDataStructureFactory<ILits> {
45
46
47
48
49
50 @Override
51 public Constr createPseudoBooleanConstraint(IVecInt literals,
52 IVec<BigInteger> coefs, boolean moreThan, BigInteger degree)
53 throws ContradictionException {
54 BigInteger diff = reduceToCard(coefs, literals);
55 degree = degree.add(diff);
56 assert coefficientsEqualToOne(coefs);
57 if (moreThan) {
58 return AtLeast.atLeastNew(solver, getVocabulary(), literals, degree
59 .intValue());
60 }
61 for (int i = 0; i < literals.size(); i++) {
62 literals.set(i, literals.get(i) ^ 1);
63 }
64 return AtLeast.atLeastNew(solver, getVocabulary(), literals, coefs
65 .size()
66 - degree.intValue());
67 }
68
69 public static boolean coefficientsEqualToOne(IVec<BigInteger> v) {
70 for (int i = 0; i < v.size(); i++) {
71 if (!v.get(i).equals(BigInteger.ONE))
72 return false;
73 }
74 return true;
75 }
76
77 private BigInteger reduceToCard(IVec<BigInteger> coefs, IVecInt literals) {
78 int diff = 0;
79 for (int i = 0; i < coefs.size(); i++) {
80 assert coefs.get(i).abs().equals(BigInteger.ONE);
81 if (coefs.get(i).signum() < 0) {
82 assert coefs.get(i).equals(BigInteger.ONE.negate());
83 diff++;
84 literals.set(i, literals.get(i) ^ 1);
85 coefs.set(i, BigInteger.ONE);
86 }
87 }
88 return BigInteger.valueOf(diff);
89 }
90
91 @Override
92 protected ILits createLits() {
93 return new Lits();
94 }
95 }