Skip to content

Commit bd49a74

Browse files
authored
Merge pull request #68 from com-github-javabdd/67-bdd-satcount-may-produce-wrong-results
#67 BDD.pathCount/satCount return a BigInteger.
2 parents 2f724f5 + bfe5a8b commit bd49a74

File tree

4 files changed

+77
-83
lines changed

4 files changed

+77
-83
lines changed

src/main/java/com/github/javabdd/BDD.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package com.github.javabdd;
1515

1616
import java.io.PrintStream;
17+
import java.math.BigDecimal;
1718
import java.math.BigInteger;
1819
import java.util.Arrays;
1920
import java.util.HashMap;
@@ -1443,7 +1444,7 @@ protected int printdot_rec(PrintStream out, int current, boolean[] visited, Hash
14431444
*
14441445
* @return the number of paths leading to the true terminal
14451446
*/
1446-
public abstract double pathCount();
1447+
public abstract BigInteger pathCount();
14471448

14481449
/**
14491450
* Calculates the number of satisfying variable assignments.
@@ -1454,7 +1455,7 @@ protected int printdot_rec(PrintStream out, int current, boolean[] visited, Hash
14541455
*
14551456
* @return the number of satisfying variable assignments
14561457
*/
1457-
public abstract double satCount();
1458+
public abstract BigInteger satCount();
14581459

14591460
/**
14601461
* Calculates the number of satisfying variable assignments to the variables in the given varset. ASSUMES THAT THE
@@ -1468,18 +1469,19 @@ protected int printdot_rec(PrintStream out, int current, boolean[] visited, Hash
14681469
* @param varset the given varset
14691470
* @return the number of satisfying variable assignments
14701471
*/
1471-
public double satCount(BDDVarSet varset) {
1472+
public BigInteger satCount(BDDVarSet varset) {
14721473
BDDFactory factory = getFactory();
14731474

14741475
if (varset.isEmpty() || isZero()) { /* empty set */
1475-
return 0.;
1476+
return BigInteger.ZERO;
14761477
}
14771478

1478-
double unused = factory.varNum();
1479+
int unused = factory.varNum();
14791480
unused -= varset.size();
1480-
unused = satCount() / Math.pow(2.0, unused);
1481+
BigDecimal unused2 = new BigDecimal(satCount()).divide(new BigDecimal(BigInteger.TWO.pow(unused)));
14811482

1482-
return unused >= 1.0 ? unused : 1.0;
1483+
BigDecimal rslt = unused2.compareTo(BigDecimal.ONE) >= 0 ? unused2 : BigDecimal.ONE;
1484+
return rslt.toBigIntegerExact();
14831485
}
14841486

14851487
/**
@@ -1489,10 +1491,14 @@ public double satCount(BDDVarSet varset) {
14891491
* Compare to bdd_satcount.
14901492
* </p>
14911493
*
1494+
* <p>
1495+
* Note that this returns a double, so it has more limited precision.
1496+
* </p>
1497+
*
14921498
* @return the logarithm of the number of satisfying variable assignments
14931499
*/
14941500
public double logSatCount() {
1495-
return Math.log(satCount());
1501+
return Math.log(satCount().doubleValue());
14961502
}
14971503

14981504
/**
@@ -1502,11 +1508,15 @@ public double logSatCount() {
15021508
* Compare to bdd_satcountset.
15031509
* </p>
15041510
*
1511+
* <p>
1512+
* Note that this returns a double, so it has more limited precision.
1513+
* </p>
1514+
*
15051515
* @param varset the given varset
15061516
* @return the logarithm of the number of satisfying variable assignments
15071517
*/
15081518
public double logSatCount(BDDVarSet varset) {
1509-
return Math.log(satCount(varset));
1519+
return Math.log(satCount(varset).doubleValue());
15101520
}
15111521

15121522
/**

src/main/java/com/github/javabdd/BDDDomain.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ public BigInteger[] getVarIndices(BDD that) {
405405
*/
406406
public BigInteger[] getVarIndices(BDD that, int max) {
407407
BDDVarSet myvarset = set(); // can't use var here, must respect subclass a factory may provide
408-
int n = (int)that.satCount(myvarset);
408+
int n = that.satCount(myvarset).intValueExact();
409409
if (max != -1 && n > max) {
410410
n = max;
411411
}

src/main/java/com/github/javabdd/BDDFactoryIntImpl.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
package com.github.javabdd;
1515

16+
import java.math.BigInteger;
1617
import java.util.Collection;
1718
import java.util.Iterator;
1819
import java.util.List;
@@ -117,9 +118,9 @@ public abstract class BDDFactoryIntImpl extends BDDFactory {
117118

118119
protected abstract int nodeCount_impl(/* bdd */int v);
119120

120-
protected abstract double pathCount_impl(/* bdd */int v);
121+
protected abstract BigInteger pathCount_impl(/* bdd */int v);
121122

122-
protected abstract double satCount_impl(/* bdd */int v);
123+
protected abstract BigInteger satCount_impl(/* bdd */int v);
123124

124125
protected abstract /* bdd */int satOne_impl(/* bdd */int v);
125126

@@ -269,7 +270,7 @@ public BDD not() {
269270
}
270271

271272
@Override
272-
public double pathCount() {
273+
public BigInteger pathCount() {
273274
return pathCount_impl(v);
274275
}
275276

@@ -306,7 +307,7 @@ public BDD restrictWith(BDD that) {
306307
}
307308

308309
@Override
309-
public double satCount() {
310+
public BigInteger satCount() {
310311
return satCount_impl(v);
311312
}
312313

src/main/java/com/github/javabdd/JFactory.java

Lines changed: 52 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.io.BufferedWriter;
1818
import java.io.IOException;
1919
import java.io.PrintStream;
20+
import java.math.BigInteger;
2021
import java.util.Arrays;
2122
import java.util.Collection;
2223
import java.util.Collections;
@@ -297,12 +298,12 @@ protected int nodeCount_impl(int v) {
297298
}
298299

299300
@Override
300-
protected double pathCount_impl(int v) {
301+
protected BigInteger pathCount_impl(int v) {
301302
return bdd_pathcount(v);
302303
}
303304

304305
@Override
305-
protected double satCount_impl(int v) {
306+
protected BigInteger satCount_impl(int v) {
306307
return bdd_satcount(v);
307308
}
308309

@@ -1062,16 +1063,16 @@ BddCacheData copy() {
10621063
}
10631064
}
10641065

1065-
private static class BddCacheDataD extends BddCacheData {
1066-
double dres;
1066+
private static class BddCacheDataBI extends BddCacheData {
1067+
BigInteger bires;
10671068

10681069
@Override
10691070
BddCacheData copy() {
1070-
BddCacheDataD that = new BddCacheDataD();
1071+
BddCacheDataBI that = new BddCacheDataBI();
10711072
that.a = this.a;
10721073
that.b = this.b;
10731074
that.c = this.c;
1074-
that.dres = this.dres;
1075+
that.bires = this.bires;
10751076
return that;
10761077
}
10771078
}
@@ -1083,9 +1084,9 @@ private static class BddCache {
10831084

10841085
BddCache copy() {
10851086
BddCache that = new BddCache();
1086-
boolean is_d = this.table instanceof BddCacheDataD[];
1087-
if (is_d) {
1088-
that.table = new BddCacheDataD[this.table.length];
1087+
boolean is_bi = this.table instanceof BddCacheDataBI[];
1088+
if (is_bi) {
1089+
that.table = new BddCacheDataBI[this.table.length];
10891090
} else {
10901091
that.table = new BddCacheDataI[this.table.length];
10911092
}
@@ -6277,110 +6278,92 @@ void varprofile_rec(int r, int[] varprofile) {
62776278
varprofile_rec(HIGH(r), varprofile);
62786279
}
62796280

6280-
double bdd_pathcount(int r) {
6281+
BigInteger bdd_pathcount(int r) {
62816282
CHECK(r);
62826283

62836284
miscid = CACHEID_PATHCOU;
62846285

62856286
if (countcache == null) {
6286-
countcache = BddCacheD_init(cachesize);
6287+
countcache = BddCacheBI_init(cachesize);
62876288
}
62886289

62896290
return bdd_pathcount_rec(r);
62906291
}
62916292

6292-
double bdd_pathcount_rec(int r) {
6293-
BddCacheDataD entry;
6294-
double size;
6293+
BigInteger bdd_pathcount_rec(int r) {
6294+
BddCacheDataBI entry;
62956295

62966296
if (ISZERO(r)) {
6297-
return 0.0;
6297+
return BigInteger.ZERO;
62986298
}
62996299
if (ISONE(r)) {
6300-
return 1.0;
6300+
return BigInteger.ONE;
63016301
}
63026302

6303-
entry = BddCache_lookupD(countcache, PATHCOUHASH(r));
6303+
entry = BddCache_lookupBI(countcache, PATHCOUHASH(r));
63046304
if (entry.a == r && entry.c == miscid) {
6305-
return entry.dres;
6305+
return entry.bires;
63066306
}
63076307

6308-
size = bdd_pathcount_rec(LOW(r)) + bdd_pathcount_rec(HIGH(r));
6308+
BigInteger size = bdd_pathcount_rec(LOW(r)).add(bdd_pathcount_rec(HIGH(r)));
63096309

63106310
entry.a = r;
63116311
entry.c = miscid;
6312-
entry.dres = size;
6312+
entry.bires = size;
63136313

63146314
return size;
63156315
}
63166316

6317-
double bdd_satcount(int r) {
6317+
BigInteger bdd_satcount(int r) {
63186318
if (ZDD) {
63196319
return bdd_pathcount(r);
63206320
}
63216321

6322-
double size = 1;
6323-
63246322
CHECK(r);
63256323

63266324
if (countcache == null) {
6327-
countcache = BddCacheD_init(cachesize);
6325+
countcache = BddCacheBI_init(cachesize);
63286326
}
63296327

63306328
miscid = CACHEID_SATCOU;
6331-
if (!ZDD) {
6332-
size = Math.pow(2.0, LEVEL(r));
6333-
}
6334-
6335-
return size * satcount_rec(r);
6336-
}
6337-
6338-
double bdd_satcountset(int r, int varset) {
6339-
double unused = bddvarnum;
6340-
int n;
6341-
6342-
if (ISCONST(varset) || ISZERO(r)) { /* empty set */
6343-
return 0.0;
6344-
}
6345-
6346-
for (n = varset; !ISCONST(n); n = HIGH(n)) {
6347-
unused--;
6329+
BigInteger size;
6330+
if (ZDD) {
6331+
size = BigInteger.ONE;
6332+
} else {
6333+
size = BigInteger.TWO.pow(LEVEL(r));
63486334
}
63496335

6350-
unused = bdd_satcount(r) / Math.pow(2.0, unused);
6351-
6352-
return unused >= 1.0 ? unused : 1.0;
6336+
return size.multiply(satcount_rec(r));
63536337
}
63546338

6355-
double satcount_rec(int root) {
6356-
BddCacheDataD entry;
6357-
double size, s;
6339+
BigInteger satcount_rec(int root) {
6340+
BddCacheDataBI entry;
63586341

63596342
if (root < 2) {
6360-
return root;
6343+
return BigInteger.valueOf(root);
63616344
}
63626345

6363-
entry = BddCache_lookupD(countcache, SATCOUHASH(root));
6346+
entry = BddCache_lookupBI(countcache, SATCOUHASH(root));
63646347
if (entry.a == root && entry.c == miscid) {
6365-
return entry.dres;
6348+
return entry.bires;
63666349
}
63676350

6368-
size = 0;
6369-
s = 1;
6351+
BigInteger size = BigInteger.ZERO;
6352+
BigInteger s = BigInteger.ONE;
63706353
if (!ZDD) {
6371-
s *= Math.pow(2.0, LEVEL(LOW(root)) - LEVEL(root) - 1);
6354+
s = s.multiply(BigInteger.TWO.pow(LEVEL(LOW(root)) - LEVEL(root) - 1));
63726355
}
6373-
size += s * satcount_rec(LOW(root));
6356+
size = size.add(s.multiply(satcount_rec(LOW(root))));
63746357

6375-
s = 1;
6358+
s = BigInteger.ONE;
63766359
if (!ZDD) {
6377-
s *= Math.pow(2.0, LEVEL(HIGH(root)) - LEVEL(root) - 1);
6360+
s = s.multiply(BigInteger.TWO.pow(LEVEL(HIGH(root)) - LEVEL(root) - 1));
63786361
}
6379-
size += s * satcount_rec(HIGH(root));
6362+
size = size.add(s.multiply(satcount_rec(HIGH(root))));
63806363

63816364
entry.a = root;
63826365
entry.c = miscid;
6383-
entry.dres = size;
6366+
entry.bires = size;
63846367

63856368
return size;
63866369
}
@@ -6942,7 +6925,7 @@ void bdd_operator_init(int cachesize) {
69426925
appexcache = BddCacheI_init(cachesize);
69436926
replacecache = BddCacheI_init(cachesize);
69446927
misccache = BddCacheI_init(cachesize);
6945-
countcache = BddCacheD_init(cachesize);
6928+
countcache = BddCacheBI_init(cachesize);
69466929
}
69476930

69486931
quantvarsetID = 0;
@@ -7050,16 +7033,16 @@ BddCache BddCacheI_init(int size) {
70507033
return cache;
70517034
}
70527035

7053-
BddCache BddCacheD_init(int size) {
7036+
BddCache BddCacheBI_init(int size) {
70547037
int n;
70557038

70567039
size = bdd_prime_gte(size);
70577040

70587041
BddCache cache = new BddCache();
7059-
cache.table = new BddCacheDataD[size];
7042+
cache.table = new BddCacheDataBI[size];
70607043

70617044
for (n = 0; n < size; n++) {
7062-
cache.table[n] = new BddCacheDataD();
7045+
cache.table[n] = new BddCacheDataBI();
70637046
cache.table[n].a = -1;
70647047
}
70657048
cache.tablesize = size;
@@ -7082,21 +7065,21 @@ int BddCache_resize(BddCache cache, int newsize) {
70827065
}
70837066
int n;
70847067

7085-
boolean is_d = cache.table instanceof BddCacheDataD[];
7068+
boolean is_bi = cache.table instanceof BddCacheDataBI[];
70867069

70877070
cache.table = null;
70887071

70897072
newsize = bdd_prime_gte(newsize);
70907073

7091-
if (is_d) {
7092-
cache.table = new BddCacheDataD[newsize];
7074+
if (is_bi) {
7075+
cache.table = new BddCacheDataBI[newsize];
70937076
} else {
70947077
cache.table = new BddCacheDataI[newsize];
70957078
}
70967079

70977080
for (n = 0; n < newsize; n++) {
7098-
if (is_d) {
7099-
cache.table[n] = new BddCacheDataD();
7081+
if (is_bi) {
7082+
cache.table[n] = new BddCacheDataBI();
71007083
} else {
71017084
cache.table[n] = new BddCacheDataI();
71027085
}
@@ -7111,8 +7094,8 @@ BddCacheDataI BddCache_lookupI(BddCache cache, int hash) {
71117094
return (BddCacheDataI)cache.table[Math.abs(hash % cache.tablesize)];
71127095
}
71137096

7114-
BddCacheDataD BddCache_lookupD(BddCache cache, int hash) {
7115-
return (BddCacheDataD)cache.table[Math.abs(hash % cache.tablesize)];
7097+
BddCacheDataBI BddCache_lookupBI(BddCache cache, int hash) {
7098+
return (BddCacheDataBI)cache.table[Math.abs(hash % cache.tablesize)];
71167099
}
71177100

71187101
void BddCache_reset(BddCache cache) {

0 commit comments

Comments
 (0)