Skip to content

Commit 14495fe

Browse files
committed
#67 BDD.pathCount/satCount return a BigInteger.
- The 'countcache' now stores BigIntegers as well. - Gives better precision for larger BDDs. - Prevents wrong results for very large BDDs.
1 parent 2f724f5 commit 14495fe

File tree

4 files changed

+102
-68
lines changed

4 files changed

+102
-68
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: 77 additions & 54 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

@@ -1076,6 +1077,20 @@ BddCacheData copy() {
10761077
}
10771078
}
10781079

1080+
private static class BddCacheDataBI extends BddCacheData {
1081+
BigInteger bires;
1082+
1083+
@Override
1084+
BddCacheData copy() {
1085+
BddCacheDataBI that = new BddCacheDataBI();
1086+
that.a = this.a;
1087+
that.b = this.b;
1088+
that.c = this.c;
1089+
that.bires = this.bires;
1090+
return that;
1091+
}
1092+
}
1093+
10791094
private static class BddCache {
10801095
BddCacheData[] table;
10811096

@@ -6277,110 +6292,92 @@ void varprofile_rec(int r, int[] varprofile) {
62776292
varprofile_rec(HIGH(r), varprofile);
62786293
}
62796294

6280-
double bdd_pathcount(int r) {
6295+
BigInteger bdd_pathcount(int r) {
62816296
CHECK(r);
62826297

62836298
miscid = CACHEID_PATHCOU;
62846299

62856300
if (countcache == null) {
6286-
countcache = BddCacheD_init(cachesize);
6301+
countcache = BddCacheBI_init(cachesize);
62876302
}
62886303

62896304
return bdd_pathcount_rec(r);
62906305
}
62916306

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

62966310
if (ISZERO(r)) {
6297-
return 0.0;
6311+
return BigInteger.ZERO;
62986312
}
62996313
if (ISONE(r)) {
6300-
return 1.0;
6314+
return BigInteger.ONE;
63016315
}
63026316

6303-
entry = BddCache_lookupD(countcache, PATHCOUHASH(r));
6317+
entry = BddCache_lookupBI(countcache, PATHCOUHASH(r));
63046318
if (entry.a == r && entry.c == miscid) {
6305-
return entry.dres;
6319+
return entry.bires;
63066320
}
63076321

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

63106324
entry.a = r;
63116325
entry.c = miscid;
6312-
entry.dres = size;
6326+
entry.bires = size;
63136327

63146328
return size;
63156329
}
63166330

6317-
double bdd_satcount(int r) {
6331+
BigInteger bdd_satcount(int r) {
63186332
if (ZDD) {
63196333
return bdd_pathcount(r);
63206334
}
63216335

6322-
double size = 1;
6323-
63246336
CHECK(r);
63256337

63266338
if (countcache == null) {
6327-
countcache = BddCacheD_init(cachesize);
6339+
countcache = BddCacheBI_init(cachesize);
63286340
}
63296341

63306342
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--;
6343+
BigInteger size;
6344+
if (ZDD) {
6345+
size = BigInteger.ONE;
6346+
} else {
6347+
size = BigInteger.TWO.pow(LEVEL(r));
63486348
}
63496349

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

6355-
double satcount_rec(int root) {
6356-
BddCacheDataD entry;
6357-
double size, s;
6353+
BigInteger satcount_rec(int root) {
6354+
BddCacheDataBI entry;
63586355

63596356
if (root < 2) {
6360-
return root;
6357+
return (root == 0) ? BigInteger.ZERO : BigInteger.ONE;
63616358
}
63626359

6363-
entry = BddCache_lookupD(countcache, SATCOUHASH(root));
6360+
entry = BddCache_lookupBI(countcache, SATCOUHASH(root));
63646361
if (entry.a == root && entry.c == miscid) {
6365-
return entry.dres;
6362+
return entry.bires;
63666363
}
63676364

6368-
size = 0;
6369-
s = 1;
6365+
BigInteger size = BigInteger.ZERO;
6366+
BigInteger s = BigInteger.ONE;
63706367
if (!ZDD) {
6371-
s *= Math.pow(2.0, LEVEL(LOW(root)) - LEVEL(root) - 1);
6368+
s = s.multiply(BigInteger.TWO.pow(LEVEL(LOW(root)) - LEVEL(root) - 1));
63726369
}
6373-
size += s * satcount_rec(LOW(root));
6370+
size = size.add(s.multiply(satcount_rec(LOW(root))));
63746371

6375-
s = 1;
6372+
s = BigInteger.ONE;
63766373
if (!ZDD) {
6377-
s *= Math.pow(2.0, LEVEL(HIGH(root)) - LEVEL(root) - 1);
6374+
s = s.multiply(BigInteger.TWO.pow(LEVEL(HIGH(root)) - LEVEL(root) - 1));
63786375
}
6379-
size += s * satcount_rec(HIGH(root));
6376+
size = size.add(s.multiply(satcount_rec(HIGH(root))));
63806377

63816378
entry.a = root;
63826379
entry.c = miscid;
6383-
entry.dres = size;
6380+
entry.bires = size;
63846381

63856382
return size;
63866383
}
@@ -6942,7 +6939,7 @@ void bdd_operator_init(int cachesize) {
69426939
appexcache = BddCacheI_init(cachesize);
69436940
replacecache = BddCacheI_init(cachesize);
69446941
misccache = BddCacheI_init(cachesize);
6945-
countcache = BddCacheD_init(cachesize);
6942+
countcache = BddCacheBI_init(cachesize);
69466943
}
69476944

69486945
quantvarsetID = 0;
@@ -7067,6 +7064,23 @@ BddCache BddCacheD_init(int size) {
70677064
return cache;
70687065
}
70697066

7067+
BddCache BddCacheBI_init(int size) {
7068+
int n;
7069+
7070+
size = bdd_prime_gte(size);
7071+
7072+
BddCache cache = new BddCache();
7073+
cache.table = new BddCacheDataBI[size];
7074+
7075+
for (n = 0; n < size; n++) {
7076+
cache.table[n] = new BddCacheDataBI();
7077+
cache.table[n].a = -1;
7078+
}
7079+
cache.tablesize = size;
7080+
7081+
return cache;
7082+
}
7083+
70707084
void BddCache_done(BddCache cache) {
70717085
if (cache == null) {
70727086
return;
@@ -7082,20 +7096,25 @@ int BddCache_resize(BddCache cache, int newsize) {
70827096
}
70837097
int n;
70847098

7099+
boolean is_bi = cache.table instanceof BddCacheDataBI[];
70857100
boolean is_d = cache.table instanceof BddCacheDataD[];
70867101

70877102
cache.table = null;
70887103

70897104
newsize = bdd_prime_gte(newsize);
70907105

7091-
if (is_d) {
7106+
if (is_bi) {
7107+
cache.table = new BddCacheDataBI[newsize];
7108+
} else if (is_d) {
70927109
cache.table = new BddCacheDataD[newsize];
70937110
} else {
70947111
cache.table = new BddCacheDataI[newsize];
70957112
}
70967113

70977114
for (n = 0; n < newsize; n++) {
7098-
if (is_d) {
7115+
if (is_bi) {
7116+
cache.table[n] = new BddCacheDataBI();
7117+
} else if (is_d) {
70997118
cache.table[n] = new BddCacheDataD();
71007119
} else {
71017120
cache.table[n] = new BddCacheDataI();
@@ -7115,6 +7134,10 @@ BddCacheDataD BddCache_lookupD(BddCache cache, int hash) {
71157134
return (BddCacheDataD)cache.table[Math.abs(hash % cache.tablesize)];
71167135
}
71177136

7137+
BddCacheDataBI BddCache_lookupBI(BddCache cache, int hash) {
7138+
return (BddCacheDataBI)cache.table[Math.abs(hash % cache.tablesize)];
7139+
}
7140+
71187141
void BddCache_reset(BddCache cache) {
71197142
if (cache == null) {
71207143
return;

0 commit comments

Comments
 (0)