OSDN Git Service

ver1.1
[nysol/mining.git] / zdd / lib / SAPPOROBDD / src / BDD+ / BDD.cc
diff --git a/zdd/lib/SAPPOROBDD/src/BDD+/BDD.cc b/zdd/lib/SAPPOROBDD/src/BDD+/BDD.cc
new file mode 100755 (executable)
index 0000000..3b93e00
--- /dev/null
@@ -0,0 +1,492 @@
+ /***************************************
+ * BDD+ Manipulator (SAPPORO-1.58)      *
+ * (Basic methods)                      *
+ * (C) Shin-ichi MINATO (Nov. 22, 2013) *
+ ****************************************/
+
+#include "BDD.h"
+
+static const char BC_Smooth = 60;
+static const char BC_Spread = 61;
+
+extern "C"
+{
+  int rand();
+};
+
+
+//--- SBDD class for default initialization ----
+
+int BDDV_Active = 0;
+
+class SBDD
+{
+public:
+  SBDD(bddword init, bddword limit) { bddinit(init, limit); }
+};
+static SBDD BDD_Manager((bddword)256, (bddword)1024);
+
+
+//----- External constant data for BDD -------
+
+const bddword BDD_MaxNode = B_VAL_MASK >> 1U;
+const int BDD_MaxVar = bddvarmax;
+
+//-------------- class BDD --------------------
+
+bddword BDD::Size() const { return bddsize(_bdd); }
+
+void BDD::Export(FILE *strm) const 
+{
+  bddword p = _bdd;
+  bddexport(strm, &p, 1);
+}
+
+void BDD::Print() const
+{
+  cout << "[ " << GetID();
+  cout << " Var:" << Top() << "(" << BDD_LevOfVar(Top()) << ")";
+  cout << " Size:" << Size() << " ]\n";
+  cout.flush();
+}
+
+BDD BDD::Swap(const int& v1, const int& v2) const
+{
+  if(v1 == v2) return *this;
+  BDD x = BDDvar(v1);
+  BDD y = BDDvar(v2);
+  BDD fx0 = At0(v1);
+  BDD fx1 = At1(v1);
+  return x & ( ~y & fx0.At1(v2) | y & fx1.At1(v2) ) |
+        ~x & ( ~y & fx0.At0(v2) | y & fx1.At0(v2) );
+}
+
+#define BDD_CACHE_CHK_RETURN(op, fx, gx) \
+  { BDD h = BDD_CacheBDD(op, fx, gx); \
+    if(h != -1) return h; \
+    BDD_RECUR_INC; }
+
+#define BDD_CACHE_ENT_RETURN(op, fx, gx, h) \
+  { BDD_RECUR_DEC; \
+    if(h != -1) BDD_CacheEnt(op, fx, gx, h.GetID()); \
+    return h; }
+
+BDD BDD::Smooth(const int& v) const
+{
+  int t = Top();
+  if(t == 0) return *this;
+  if(BDD_LevOfVar(t) <= BDD_LevOfVar(v)) return 1;
+  bddword fx = GetID();
+  bddword gx = BDDvar(v).GetID();
+  BDD_CACHE_CHK_RETURN(BC_Smooth, fx, gx);
+  BDD x = BDDvar(t);
+  BDD h = (~x & At0(t).Smooth(v))|(x & At1(t).Smooth(v));
+  BDD_CACHE_ENT_RETURN(BC_Smooth, fx, gx, h);
+}
+
+BDD BDD::Spread(const int& k) const
+{
+  int t = Top();
+  if(t == 0) return *this;
+  if(k == 0) return *this;
+  if(k < 0) BDDerr("BDD::Spread: k < 0.",k);
+  bddword fx = GetID();
+  bddword gx = BDDvar(k).GetID();
+  BDD_CACHE_CHK_RETURN(BC_Spread, fx, gx);
+  BDD x = BDDvar(t);
+  BDD f0 = At0(t);
+  BDD f1 = At1(t);
+  BDD h = (~x & f0.Spread(k)) | (x & f1.Spread(k))
+    | (~x & f1.Spread(k-1)) | (x & f0.Spread(k-1));
+  BDD_CACHE_ENT_RETURN(BC_Spread, fx, gx, h);
+}
+
+//----- External functions for BDD -------
+
+void BDD_Init(bddword init, bddword limit)
+{
+  bddinit(init, limit);
+  BDDV_Active = 0;
+}
+       
+int BDD_NewVarOfLev(int lev)
+{
+  if(lev > BDD_TopLev() + 1)
+    BDDerr("BDD_NewVarOfLev:Invald lev ", (bddword)lev);
+  return bddnewvaroflev(lev);
+}
+
+int BDD_VarUsed(void) { return bddvarused(); }
+
+bddword BDD_Used(void) { return bddused(); }
+
+void BDD_GC() { bddgc(); }
+
+BDD BDD_Import(FILE *strm)
+{
+       bddword bdd;
+       if(bddimport(strm, &bdd, 1)) return -1;
+       return BDD_ID(bdd);
+}
+
+BDD BDD_Random(int level, int density)
+{
+  if(level < 0)
+    BDDerr("BDD_Random: level < 0.",level);
+  if(level == 0) return ((rand()%100) < density)? 1: 0;
+  return (BDDvar(BDD_VarOfLev(level))
+        & BDD_Random(level-1, density)) |
+         (~BDDvar(BDD_VarOfLev(level))
+        & BDD_Random(level-1, density));
+}
+
+void BDDerr(const char* msg)
+{
+  cerr << "<ERROR> " << msg << " \n";
+  exit(1);
+}
+
+void BDDerr(const char* msg, bddword key)
+{
+  cerr << "<ERROR> " << msg << " (" << key << ")\n";
+  exit(1);
+}
+
+void BDDerr(const char* msg, const char* name)
+{
+  cerr << "<ERROR> " << msg << " (" << name << ")\n";
+  exit(1);
+}
+
+
+//----- External constant data for BDDV -------
+
+const int BDDV_SysVarTop = 20;
+const int BDDV_MaxLen = 1 << BDDV_SysVarTop;
+const int BDDV_MaxLenImport = 1000;
+
+
+//--------------- class BDDV ------------------------
+
+BDDV::BDDV(const BDD& f, int len)
+{
+  if(len < 0) BDDerr("BDDV::BDDV: len < 0.", len);
+  if(len > BDDV_MaxLen) BDDerr("BDDV::BDDV: Too large len.", len);
+  int t = f.Top();
+  if(t > 0 && BDD_LevOfVar(t) > BDD_TopLev())
+    BDDerr("BDDV::BDDV: Invalid Top Var.", t);
+  _bdd = (len == 0)? 0: f;
+  _len = (f == -1)? 1: len;
+  _lev = GetLev(len);
+}
+
+BDDV BDDV::operator<<(int shift) const
+{
+  if(!Uniform()) return (Former() << shift) || (Latter() << shift);
+  BDDV hv;
+  if((hv._bdd = _bdd << shift) == -1) return BDDV(-1);
+  hv._len = _len;
+  hv._lev = _lev;
+  return hv;
+}
+
+BDDV BDDV::operator>>(int shift) const
+{
+  if(!Uniform()) return (Former() >> shift) || (Latter() >> shift);
+  BDDV hv;
+  if((hv._bdd = _bdd >> shift) == -1) return BDDV(-1);
+  hv._len = _len;
+  hv._lev = _lev;
+  return hv;
+}
+
+BDDV BDDV::Cofact(const BDDV& fv) const
+{
+  if(_lev > 0)
+    return Former().Cofact(fv.Former()) || Latter().Cofact(fv.Latter());
+  BDDV hv;
+  if((hv._bdd = _bdd.Cofact(fv._bdd)) == -1) return BDDV(-1);
+  if(_len != fv._len) BDDerr("BDDV::Cofact: Length mismatch.");
+  hv._len = _len;
+  // hv._lev = _lev; (always zero)
+  return hv;
+}
+
+BDDV BDDV::Swap(int v1, int v2) const
+{
+  if(BDD_LevOfVar(v1) > BDD_TopLev())
+    BDDerr("BDDV::Swap: Invalid VarID.", v1);
+  if(BDD_LevOfVar(v2) > BDD_TopLev())
+    BDDerr("BDDV::Swap: Invalid VarID.", v2);
+  BDDV hv;
+  if((hv._bdd = _bdd.Swap(v1, v2)) == -1) return BDDV(-1);
+  hv._len = _len;
+  hv._lev = _lev;
+  return hv;
+}
+
+int BDDV::Top() const
+{
+  if(Uniform()) return _bdd.Top();
+  int t0 = Former().Top();
+  int t1 = Latter().Top();
+  if(BDD_LevOfVar(t0) > BDD_LevOfVar(t1)) return t0;
+  else return t1;
+}
+
+bddword BDDV::Size() const
+{
+  bddword* bddv = new bddword[_len];
+  for(int i=0; i<_len; i++) bddv[i] = GetBDD(i).GetID(); 
+  bddword s = bddvsize(bddv, _len);
+  delete[] bddv;
+  return s;
+}
+
+void BDDV::Export(FILE *strm) const
+{
+  bddword* bddv = new bddword[_len];
+  for(int i=0; i<_len; i++) bddv[i] = GetBDD(i).GetID(); 
+  bddexport(strm, bddv, _len);
+  delete[] bddv;
+}
+
+BDDV BDDV::Spread(int k) const
+{
+  if(Uniform()) return _bdd.Spread(k);
+  return Former().Spread(k) || Latter().Spread(k);
+}
+
+BDDV BDDV::Part(int start, int len) const
+{
+  if(_bdd == -1) return *this;
+  if(len == 0) return BDDV();
+
+  if(start < 0 || start + len  > _len)
+    BDDerr("BDDV::Part: Illegal index.");
+  
+  if(start == 0 && len == _len) return *this;
+  
+  int half = 1 << (_lev-1);
+  
+  if(start + len <= half) return Former().Part(start, len);
+  if(start >= half) return Latter().Part(start - half, len);
+  return Former().Part(start, half - start)
+      || Latter().Part(0, start + len - half);
+}
+
+BDD BDDV::GetBDD(int index) const
+{
+  if(index < 0 || index >= _len)
+    BDDerr("BDDV::GetBDD: Illegal index.",index);
+  if(_len == 1) return _bdd;
+  BDD f = _bdd;
+  for(int i=_lev-1; i>=0; i--)
+    if((index & (1<<i)) == 0) f = f.At0(i + 1);
+    else f = f.At1(i + 1);
+  return f;
+}
+
+void BDDV::Print() const
+{
+  for(int i=0; i<_len; i++)
+  {
+    cout << "f" << i << ": ";
+    GetBDD(i).Print();
+  }
+  cout << "Size= " << Size() << "\n\n";
+  cout.flush();
+}
+
+//----- External functions for BDD Vector -------
+
+void BDDV_Init(bddword init, bddword limit)
+{
+  bddinit(init, limit);
+  for(int i=0; i<BDDV_SysVarTop; i++) bddnewvar();
+  BDDV_Active = 1;
+}
+       
+BDDV operator||(const BDDV& fv, const BDDV& gv)
+{
+  if(fv._len == 0) return gv;
+  if(gv._len == 0) return fv;
+  if(fv._len != (1 << fv._lev))
+    return BDDV(fv).Former() || (BDDV(fv).Latter() || gv);
+  if(fv._len < gv._len)
+    return (fv || BDDV(gv).Former()) || BDDV(gv).Latter();
+  BDDV hv;
+  BDD x = BDDvar(fv._lev + 1);
+  if((hv._bdd = (~x & fv._bdd)|(x & gv._bdd)) == -1) return BDDV(-1);
+  if((hv._len = fv._len + gv._len) > BDDV_MaxLen)
+    BDDerr("BDDV::operatop||: Too large len.", hv._len);
+  hv._lev = fv._lev + 1;
+  return hv;
+}
+
+BDDV BDDV_Mask1(int index, int len)
+{
+  if(len < 0) BDDerr("BDDV_Mask1: len < 0.", len);
+  if(index < 0 || index >= len)
+    BDDerr("BDDV_Mask1: Illegal index.", index);
+  return BDDV(0,index)||BDDV(1,1)||BDDV(0,len-index-1);
+}
+
+BDDV BDDV_Mask2(int index, int len)
+{
+  if(len < 0) BDDerr("BDDV_Mask2: len < 0.", len);
+  if(index < 0 || index > len)
+    BDDerr("BDDV_Mask2: Illegal index.", index);
+  return BDDV(0,index)||BDDV(1,len-index);
+}
+
+#define IMPORTHASH(x) (((x >> 1) ^ (x >> 16)) & (hashsize - 1))
+
+#ifdef B_64
+#  define B_STRTOI strtoll
+#else
+#  define B_STRTOI strtol
+#endif
+
+BDDV BDDV_Import(FILE *strm)
+{
+  int inv, e;
+  bddword hashsize;
+  BDD f, f0, f1;
+  char s[256];
+  bddword *hash1;
+  BDD *hash2;
+
+  if(fscanf(strm, "%s", &s) == EOF) return BDDV(-1);
+  if(strcmp(s, "_i") != 0) return BDDV(-1);
+  if(fscanf(strm, "%s", &s) == EOF) return BDDV(-1);
+  int n = strtol(s, NULL, 10);
+  while(n > BDD_TopLev()) BDD_NewVar();
+
+  if(fscanf(strm, "%s", &s) == EOF) return BDDV(-1);
+  if(strcmp(s, "_o") != 0) return BDDV(-1);
+  if(fscanf(strm, "%s", &s) == EOF) return BDDV(-1);
+  int m = strtol(s, NULL, 10);
+
+  if(fscanf(strm, "%s", &s) == EOF) return BDDV(-1);
+  if(strcmp(s, "_n") != 0) return BDDV(-1);
+  if(fscanf(strm, "%s", &s) == EOF) return BDDV(-1);
+  bddword n_nd = B_STRTOI(s, NULL, 10);
+
+  for(hashsize = 1; hashsize < (n_nd<<1); hashsize <<= 1)
+    ; /* empty */
+  hash1 = new bddword[hashsize];
+  if(hash1 == 0) return BDDV(-1);
+  hash2 = new BDD[hashsize];
+  if(hash2 == 0) { delete[] hash1; return BDDV(-1); }
+  for(bddword ix=0; ix<hashsize; ix++)
+  {
+    hash1[ix] = B_VAL_MASK;
+    hash2[ix] = 0;
+  }
+
+  e = 0;
+  for(bddword ix=0; ix<n_nd; ix++)
+  {
+    if(fscanf(strm, "%s", &s) == EOF) { e = 1; break; }
+    bddword nd = B_STRTOI(s, NULL, 10);
+    
+    if(fscanf(strm, "%s", &s) == EOF) { e = 1; break; }
+    int lev = strtol(s, NULL, 10);
+    int var = bddvaroflev(lev);
+
+    if(fscanf(strm, "%s", &s) == EOF) { e = 1; break; }
+    if(strcmp(s, "F") == 0) f0 = 0;
+    else if(strcmp(s, "T") == 0) f0 = 1;
+    else
+    {
+      bddword nd0 = B_STRTOI(s, NULL, 10);
+
+      bddword ixx = IMPORTHASH(nd0);
+      while(hash1[ixx] != nd0)
+      {
+        if(hash1[ixx] == B_VAL_MASK)
+          BDDerr("BDDV_Import(): internal error", ixx);
+        ixx++;
+        ixx &= (hashsize-1);
+      }
+      f0 = hash2[ixx];
+    }
+
+    if(fscanf(strm, "%s", &s) == EOF) { e = 1; break; }
+    if(strcmp(s, "F") == 0) f1 = 0;
+    else if(strcmp(s, "T") == 0) f1 = 1;
+    else
+    {
+      bddword nd1 = B_STRTOI(s, NULL, 10);
+      if(nd1 & 1) { inv = 1; nd1 ^= 1; }
+      else inv = 0;
+  
+      bddword ixx = IMPORTHASH(nd1);
+      while(hash1[ixx] != nd1)
+      {
+        if(hash1[ixx] == B_VAL_MASK)
+          BDDerr("BDDV_Import(): internal error", ixx);
+        ixx++;
+        ixx &= (hashsize-1);
+      }
+      f1 = (inv)? ~hash2[ixx]: hash2[ixx];
+    }
+
+    BDD x = BDDvar(var);
+    f = (x & f1) | (~x & f0);
+    if(f == -1) { e = 1; break; }
+
+    bddword ixx = IMPORTHASH(nd);
+    while(hash1[ixx] != B_VAL_MASK)
+    {
+      if(hash1[ixx] == nd)
+        BDDerr("BDDV_Import(): internal error", ixx);
+      ixx++;
+      ixx &= (hashsize-1);
+    }
+    hash1[ixx] = nd;
+    hash2[ixx] = f;
+  }
+
+  if(e)
+  {
+    delete[] hash2;
+    delete[] hash1;
+    return BDDV(-1);
+  }
+
+  BDDV v = BDDV();
+  for(int i=0; i<m; i++)
+  {
+    if(fscanf(strm, "%s", &s) == EOF)
+    {
+      delete[] hash2;
+      delete[] hash1;
+      return BDDV(-1);
+    }
+    bddword nd = B_STRTOI(s, NULL, 10);
+    if(strcmp(s, "F") == 0) v = v || BDD(0);
+    else if(strcmp(s, "T") == 0) v = v || BDD(1);
+    else
+    {
+      if(nd & 1) { inv = 1; nd ^= 1; }
+      else inv = 0;
+  
+      bddword ixx = IMPORTHASH(nd);
+      while(hash1[ixx] != nd)
+      {
+        if(hash1[ixx] == B_VAL_MASK)
+          BDDerr("BDDV_Import(): internal error", ixx);
+        ixx++;
+        ixx &= (hashsize-1);
+      }
+      v = v || (inv? ~hash2[ixx]: hash2[ixx]);
+    }
+  }
+
+  delete[] hash2;
+  delete[] hash1;
+  return v;
+}
+