nysol-zdd 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/ext/zdd_so/BDD.cc +495 -0
  3. data/ext/zdd_so/BDD.h +356 -0
  4. data/ext/zdd_so/BDDDG.cc +1818 -0
  5. data/ext/zdd_so/BDDDG.h +107 -0
  6. data/ext/zdd_so/BDDHASH.cc +91 -0
  7. data/ext/zdd_so/BtoI.cc +503 -0
  8. data/ext/zdd_so/BtoI.h +144 -0
  9. data/ext/zdd_so/CtoI.cc +1072 -0
  10. data/ext/zdd_so/CtoI.h +186 -0
  11. data/ext/zdd_so/MLZBDDV.cc +153 -0
  12. data/ext/zdd_so/MLZBDDV.h +42 -0
  13. data/ext/zdd_so/SOP.cc +608 -0
  14. data/ext/zdd_so/SOP.h +199 -0
  15. data/ext/zdd_so/ZBDD.cc +1035 -0
  16. data/ext/zdd_so/ZBDD.h +243 -0
  17. data/ext/zdd_so/ZBDDDG.cc +1834 -0
  18. data/ext/zdd_so/ZBDDDG.h +105 -0
  19. data/ext/zdd_so/ZBDDHASH.cc +91 -0
  20. data/ext/zdd_so/bddc.c +2816 -0
  21. data/ext/zdd_so/bddc.h +132 -0
  22. data/ext/zdd_so/extconf.rb +25 -0
  23. data/ext/zdd_so/include/aheap.c +211 -0
  24. data/ext/zdd_so/include/aheap.h +111 -0
  25. data/ext/zdd_so/include/base.c +93 -0
  26. data/ext/zdd_so/include/base.h +60 -0
  27. data/ext/zdd_so/include/itemset.c +473 -0
  28. data/ext/zdd_so/include/itemset.h +153 -0
  29. data/ext/zdd_so/include/problem.c +371 -0
  30. data/ext/zdd_so/include/problem.h +160 -0
  31. data/ext/zdd_so/include/queue.c +518 -0
  32. data/ext/zdd_so/include/queue.h +177 -0
  33. data/ext/zdd_so/include/sgraph.c +331 -0
  34. data/ext/zdd_so/include/sgraph.h +170 -0
  35. data/ext/zdd_so/include/stdlib2.c +832 -0
  36. data/ext/zdd_so/include/stdlib2.h +746 -0
  37. data/ext/zdd_so/include/trsact.c +723 -0
  38. data/ext/zdd_so/include/trsact.h +167 -0
  39. data/ext/zdd_so/include/vec.c +583 -0
  40. data/ext/zdd_so/include/vec.h +159 -0
  41. data/ext/zdd_so/lcm-vsop.cc +596 -0
  42. data/ext/zdd_so/print.cc +683 -0
  43. data/ext/zdd_so/table.cc +330 -0
  44. data/ext/zdd_so/vsop.h +88 -0
  45. data/ext/zdd_so/zdd_so.cpp +3277 -0
  46. data/lib/nysol/zdd.rb +31 -0
  47. metadata +131 -0
@@ -0,0 +1,243 @@
1
+ /*********************************************
2
+ * ZBDD+ Manipulator (SAPPORO-1.58) - Header *
3
+ * (C) Shin-ichi MINATO (Nov. 22, 2013) *
4
+ *********************************************/
5
+
6
+ class ZBDD;
7
+ class ZBDDV;
8
+
9
+ #ifndef _ZBDD_
10
+ #define _ZBDD_
11
+
12
+ #include "BDD.h"
13
+
14
+ class SeqBDD;
15
+
16
+ class ZBDD
17
+ {
18
+ bddword _zbdd;
19
+
20
+ public:
21
+ ZBDD(void) { _zbdd = bddempty; }
22
+ ZBDD(int v) { _zbdd = (v==0)? bddempty:(v>0)? bddsingle:bddnull; }
23
+ ZBDD(const ZBDD& f) { _zbdd = bddcopy(f._zbdd); }
24
+
25
+ ~ZBDD(void) { bddfree(_zbdd); }
26
+
27
+ ZBDD& operator=(const ZBDD& f) {
28
+ if(_zbdd != f._zbdd) { bddfree(_zbdd); _zbdd = bddcopy(f._zbdd); }
29
+ return *this;
30
+ }
31
+
32
+ ZBDD& operator&=(const ZBDD& f)
33
+ { ZBDD h; h._zbdd = bddintersec(_zbdd, f._zbdd); return *this = h; }
34
+
35
+ ZBDD& operator+=(const ZBDD& f)
36
+ { ZBDD h; h._zbdd = bddunion(_zbdd, f._zbdd); return *this = h; }
37
+
38
+ ZBDD& operator-=(const ZBDD& f)
39
+ { ZBDD h; h._zbdd = bddsubtract(_zbdd, f._zbdd); return *this = h; }
40
+
41
+ ZBDD& operator<<=(int s)
42
+ { ZBDD h; h._zbdd = bddlshift(_zbdd, s); return *this = h; }
43
+
44
+ ZBDD& operator>>=(int s)
45
+ { ZBDD h; h._zbdd = bddrshift(_zbdd, s); return *this = h; }
46
+
47
+ ZBDD& operator*=(const ZBDD&);
48
+ ZBDD& operator/=(const ZBDD&);
49
+ ZBDD& operator%=(const ZBDD&);
50
+
51
+ ZBDD operator<<(int s) const
52
+ { ZBDD h; h._zbdd = bddlshift(_zbdd, s); return h; }
53
+
54
+ ZBDD operator>>(int s) const
55
+ { ZBDD h; h._zbdd = bddrshift(_zbdd, s); return h; }
56
+
57
+ int Top(void) const { return bddtop(_zbdd); }
58
+
59
+ ZBDD OffSet(int v) const
60
+ { ZBDD h; h._zbdd = bddoffset(_zbdd, v); return h; }
61
+
62
+ ZBDD OnSet(int v) const
63
+ { ZBDD h; h._zbdd = bddonset(_zbdd, v); return h; }
64
+
65
+ ZBDD OnSet0(int v) const
66
+ { ZBDD h; h._zbdd = bddonset0(_zbdd, v); return h; }
67
+
68
+ ZBDD Change(int v) const
69
+ { ZBDD h; h._zbdd = bddchange(_zbdd, v); return h; }
70
+
71
+ bddword GetID(void) const { return _zbdd; }
72
+ bddword Size(void) const { return bddsize(_zbdd); }
73
+ bddword Card(void) const { return bddcard(_zbdd); }
74
+ bddword Lit(void) const { return bddlit(_zbdd); }
75
+ bddword Len(void) const { return bddlen(_zbdd); }
76
+
77
+ void Export(FILE *strm = stdout) const;
78
+ void XPrint(void) const;
79
+ void Print(void) const;
80
+ void PrintPla(void) const;
81
+
82
+ ZBDD Swap(int, int) const;
83
+ ZBDD Restrict(const ZBDD&) const;
84
+ ZBDD Permit(const ZBDD&) const;
85
+ ZBDD PermitSym(int) const;
86
+ ZBDD Support(void) const
87
+ { ZBDD h; h._zbdd = bddsupport(_zbdd); return h; }
88
+ ZBDD Always(void) const;
89
+
90
+ int SymChk(int, int) const;
91
+ ZBDD SymGrp(void) const;
92
+ ZBDD SymGrpNaive(void) const;
93
+
94
+ ZBDD SymSet(int) const;
95
+ int ImplyChk(int, int) const;
96
+ int CoImplyChk(int, int) const;
97
+ ZBDD ImplySet(int) const;
98
+ ZBDD CoImplySet(int) const;
99
+
100
+ int IsPoly(void) const;
101
+ ZBDD Divisor(void) const;
102
+
103
+ ZBDD ZLev(int lev, int last = 0) const;
104
+ void SetZSkip(void) const;
105
+ ZBDD Intersec(const ZBDD&) const;
106
+
107
+ friend ZBDD ZBDD_ID(bddword);
108
+
109
+ //friend class SeqBDD;
110
+ };
111
+
112
+ extern ZBDD operator*(const ZBDD&, const ZBDD&);
113
+ extern ZBDD operator/(const ZBDD&, const ZBDD&);
114
+ extern ZBDD ZBDD_Meet(const ZBDD&, const ZBDD&);
115
+ extern ZBDD ZBDD_Random(int, int density = 50);
116
+ extern ZBDD ZBDD_Import(FILE *strm = stdin);
117
+
118
+ extern ZBDD ZBDD_LCM_A(char *, int);
119
+ extern ZBDD ZBDD_LCM_C(char *, int);
120
+ extern ZBDD ZBDD_LCM_M(char *, int);
121
+
122
+ inline ZBDD ZBDD_ID(bddword zbdd)
123
+ { ZBDD h; h._zbdd = zbdd; return h; }
124
+
125
+ inline ZBDD BDD_CacheZBDD(char op, bddword fx, bddword gx)
126
+ { return ZBDD_ID(bddcopy(bddrcache(op, fx, gx))); }
127
+
128
+ inline ZBDD operator&(const ZBDD& f, const ZBDD& g)
129
+ { return ZBDD_ID(bddintersec(f.GetID(), g.GetID())); }
130
+
131
+ inline ZBDD operator+(const ZBDD& f, const ZBDD& g)
132
+ { return ZBDD_ID(bddunion(f.GetID(), g.GetID())); }
133
+
134
+ inline ZBDD operator-(const ZBDD& f, const ZBDD& g)
135
+ { return ZBDD_ID(bddsubtract(f.GetID(), g.GetID())); }
136
+
137
+ inline ZBDD operator%(const ZBDD& f, const ZBDD& p)
138
+ { return f - (f/p) * p; }
139
+
140
+ inline int operator==(const ZBDD& f, const ZBDD& g)
141
+ { return f.GetID() == g.GetID(); }
142
+
143
+ inline int operator!=(const ZBDD& f, const ZBDD& g)
144
+ { return !(f == g); }
145
+
146
+ inline ZBDD& ZBDD::operator*=(const ZBDD& f)
147
+ { return *this = *this * f; }
148
+
149
+ inline ZBDD& ZBDD::operator/=(const ZBDD& f)
150
+ { return *this = *this / f; }
151
+
152
+ inline ZBDD& ZBDD::operator%=(const ZBDD& f)
153
+ { return *this = *this % f; }
154
+
155
+
156
+ class ZBDDV
157
+ {
158
+ ZBDD _zbdd;
159
+
160
+ public:
161
+ ZBDDV(void) { _zbdd = 0; }
162
+ ZBDDV(const ZBDDV& fv) { _zbdd = fv._zbdd; }
163
+ ZBDDV(const ZBDD& f, int location = 0);
164
+ ~ZBDDV(void) { }
165
+
166
+ ZBDDV& operator=(const ZBDDV& fv) { _zbdd = fv._zbdd; return *this; }
167
+ ZBDDV& operator&=(const ZBDDV& fv) { _zbdd &= fv._zbdd; return *this; }
168
+ ZBDDV& operator+=(const ZBDDV& fv) { _zbdd += fv._zbdd; return *this; }
169
+ ZBDDV& operator-=(const ZBDDV& fv) { _zbdd -= fv._zbdd; return *this; }
170
+ ZBDDV& operator<<=(int);
171
+ ZBDDV& operator>>=(int);
172
+
173
+ ZBDDV operator<<(int) const;
174
+ ZBDDV operator>>(int) const;
175
+
176
+ ZBDDV OffSet(int) const;
177
+ ZBDDV OnSet(int) const;
178
+ ZBDDV OnSet0(int) const;
179
+ ZBDDV Change(int) const;
180
+ ZBDDV Swap(int, int) const;
181
+
182
+ int Top(void) const;
183
+ int Last(void) const;
184
+ ZBDDV Mask(int start, int length = 1) const;
185
+ ZBDD GetZBDD(int) const;
186
+
187
+ ZBDD GetMetaZBDD(void) const { return _zbdd; }
188
+ bddword Size(void) const;
189
+ void Print(void) const;
190
+ void Export(FILE *strm = stdout) const;
191
+ int PrintPla(void) const;
192
+ void XPrint(void) const;
193
+
194
+ friend ZBDDV operator&(const ZBDDV&, const ZBDDV&);
195
+ friend ZBDDV operator+(const ZBDDV&, const ZBDDV&);
196
+ friend ZBDDV operator-(const ZBDDV&, const ZBDDV&);
197
+ };
198
+
199
+ extern ZBDDV ZBDDV_Import(FILE *strm = stdin);
200
+
201
+ inline ZBDDV operator&(const ZBDDV& fv, const ZBDDV& gv)
202
+ { ZBDDV hv; hv._zbdd = fv._zbdd & gv._zbdd; return hv; }
203
+ inline ZBDDV operator+(const ZBDDV& fv, const ZBDDV& gv)
204
+ { ZBDDV hv; hv._zbdd = fv._zbdd + gv._zbdd; return hv; }
205
+ inline ZBDDV operator-(const ZBDDV& fv, const ZBDDV& gv)
206
+ { ZBDDV hv; hv._zbdd = fv._zbdd - gv._zbdd; return hv; }
207
+ inline int operator==(const ZBDDV& fv, const ZBDDV& gv)
208
+ { return fv.GetMetaZBDD() == gv.GetMetaZBDD(); }
209
+ inline int operator!=(const ZBDDV& fv, const ZBDDV& gv)
210
+ { return !(fv == gv); }
211
+
212
+ inline ZBDDV& ZBDDV::operator<<=(int s)
213
+ { return *this = *this << s; }
214
+
215
+ inline ZBDDV& ZBDDV::operator>>=(int s)
216
+ { return *this = *this >> s; }
217
+
218
+ class ZBDD_Hash;
219
+ class ZBDD_Hash
220
+ {
221
+ struct ZBDD_Entry
222
+ {
223
+ ZBDD _key;
224
+ void* _ptr;
225
+ ZBDD_Entry(void){ _key = -1; }
226
+ };
227
+
228
+ bddword _amount;
229
+ bddword _hashSize;
230
+ ZBDD_Entry* _wheel;
231
+
232
+ ZBDD_Entry* GetEntry(ZBDD);
233
+ void Enlarge(void);
234
+ public:
235
+ ZBDD_Hash(void);
236
+ ~ZBDD_Hash(void);
237
+ void Clear(void);
238
+ void Enter(ZBDD, void *);
239
+ void* Refer(ZBDD);
240
+ bddword Amount(void);
241
+ };
242
+
243
+ #endif // _ZBDD_
@@ -0,0 +1,1834 @@
1
+ /**********************************************
2
+ * ZBDDDG - Decomposition Graph (SAPPORO-1.59)*
3
+ * (C) Shin-ichi MINATO (Dec. 10, 2013) *
4
+ **********************************************/
5
+
6
+ #include "ZBDDDG.h"
7
+
8
+ using std::cout;
9
+ using std::cerr;
10
+
11
+ ZBDDDG_Tag::ZBDDDG_Tag()
12
+ {
13
+ _dg = 0;
14
+ _ndx = ZBDDDG_NIL;
15
+ }
16
+
17
+ int ZBDDDG_Tag::Set(ZBDDDG* dg, bddword ndx)
18
+ {
19
+ _dg = dg;
20
+ _ndx = ndx;
21
+ if(_ndx >= _dg->_nodeUsed) return 1;
22
+ _lkx = _dg->_nodeA[_ndx]._lkx;
23
+ return 0;
24
+ }
25
+
26
+ bddword ZBDDDG_Tag::TopNdx()
27
+ {
28
+ _lkx = _dg->_nodeA[_ndx]._lkx;
29
+ if(_lkx == ZBDDDG_NIL) return ZBDDDG_NIL;
30
+ return _dg->_linkA[_lkx]._ndx;
31
+ }
32
+
33
+ bddword ZBDDDG_Tag::NextNdx()
34
+ {
35
+ _lkx = _dg->_linkA[_lkx]._nxt;
36
+ if(_lkx == ZBDDDG_NIL) return ZBDDDG_NIL;
37
+ return _dg->_linkA[_lkx]._ndx;
38
+ }
39
+
40
+ char ZBDDDG_Tag::Type()
41
+ {
42
+ return _dg->_nodeA[_ndx]._type;
43
+ }
44
+
45
+ ZBDD ZBDDDG_Tag::Func()
46
+ {
47
+ return _dg->_nodeA[_ndx]._f;
48
+ }
49
+
50
+ ZBDDDG::ZBDDDG()
51
+ {
52
+ _nodeA = 0;
53
+ _linkA = 0;
54
+ _hashWheel = 0;
55
+ Clear();
56
+ }
57
+
58
+ ZBDDDG::~ZBDDDG()
59
+ {
60
+ delete[] _hashWheel;
61
+ delete[] _linkA;
62
+ delete[] _nodeA;
63
+ }
64
+
65
+ void ZBDDDG::Clear()
66
+ {
67
+ delete[] _hashWheel;
68
+ delete[] _linkA;
69
+ delete[] _nodeA;
70
+
71
+ _nodeSize = ZBDDDG_InitSize;
72
+ _nodeA = new Node[_nodeSize];
73
+ _nodeUsed = 0;
74
+ _linkSize = ZBDDDG_InitSize;
75
+ _linkA = new NodeLink[_linkSize];
76
+ _linkUsed = 0;
77
+ bddword hashSize = _nodeSize << 1;
78
+ _hashWheel = new bddword[hashSize];
79
+ for(bddword i=0; i<hashSize; i++) _hashWheel[i] = ZBDDDG_NIL;
80
+ _c0 = NewNdx(0, ZBDDDG_C0);
81
+ _c1 = NewNdx(1, ZBDDDG_P1);
82
+ LinkNodes(_c1, _c0);
83
+ }
84
+
85
+ bddword ZBDDDG::HashIndex(ZBDD key)
86
+ {
87
+ bddword id = key.GetID();
88
+ bddword hashSize = _nodeSize << 1;
89
+ bddword hash = (id+(id>>10)+(id>>20)) & (hashSize - 1);
90
+ bddword i = hash;
91
+ while(_hashWheel[i] != ZBDDDG_NIL)
92
+ {
93
+ ZBDD f = _nodeA[_hashWheel[i]]._f;
94
+ if(key == f) return i;
95
+ i++;
96
+ i &= (hashSize -1);
97
+ }
98
+ return i;
99
+ }
100
+
101
+ bddword ZBDDDG::NewNdx(ZBDD f, char type)
102
+ {
103
+ if(_nodeUsed == _nodeSize)
104
+ if(EnlargeNode()) return ZBDDDG_NIL;
105
+ bddword ndx = _nodeUsed++;
106
+ _nodeA[ndx]._f = f;
107
+ _nodeA[ndx]._type = type;
108
+ bddword i = HashIndex(f);
109
+ if(_hashWheel[i] != ZBDDDG_NIL)
110
+ {
111
+ cerr << "<ERROR> ZBDDDG::NewNdx(): Duplicate node\n";
112
+ exit(1);
113
+ }
114
+ _hashWheel[i] = ndx;
115
+ return ndx;
116
+ }
117
+
118
+ int ZBDDDG::EnlargeNode()
119
+ {
120
+ bddword oldHS = _nodeSize << 1;
121
+ Node* oldArray = _nodeA;
122
+ bddword* oldWheel = _hashWheel;
123
+
124
+ _nodeSize <<= 2;
125
+ _nodeA = new Node[_nodeSize];
126
+ bddword hashSize = _nodeSize << 1;
127
+ _hashWheel = new bddword[hashSize];
128
+ if(_nodeA == 0 || _hashWheel == 0)
129
+ {
130
+ cerr << "<ERROR> ZBDDDG::EnlargeNode(): Memory overflow (";
131
+ cerr << _nodeSize << ")\n";
132
+ return 1;
133
+ }
134
+ for(bddword i=0; i<_nodeUsed; i++)
135
+ {
136
+ _nodeA[i]._lkx = oldArray[i]._lkx;
137
+ _nodeA[i]._f = oldArray[i]._f;
138
+ _nodeA[i]._type = oldArray[i]._type;
139
+ _nodeA[i]._mark = oldArray[i]._mark;
140
+ _nodeA[i]._ndxP = oldArray[i]._ndxP;
141
+ }
142
+ for(bddword i=0; i<hashSize; i++) _hashWheel[i] = ZBDDDG_NIL;
143
+ for(bddword i=0; i<oldHS; i++)
144
+ {
145
+ bddword ndx = oldWheel[i];
146
+ if(ndx != ZBDDDG_NIL)
147
+ {
148
+ ZBDD f = _nodeA[ndx]._f;
149
+ _hashWheel[HashIndex(f)] = ndx;
150
+ }
151
+ }
152
+ delete[] oldArray;
153
+ delete[] oldWheel;
154
+ return 0;
155
+ }
156
+
157
+ bddword ZBDDDG::NewLkx(bddword ndx)
158
+ {
159
+ if(_linkUsed == _linkSize)
160
+ if(EnlargeLink()) return ZBDDDG_NIL;
161
+ bddword lkx = _linkUsed++;
162
+ _linkA[lkx]._ndx = ndx;
163
+ return lkx;
164
+ }
165
+
166
+ int ZBDDDG::EnlargeLink()
167
+ {
168
+ NodeLink* oldArray = _linkA;
169
+
170
+ _linkSize <<= 2;
171
+ _linkA = new NodeLink[_linkSize];
172
+ if(_linkA == 0)
173
+ {
174
+ cerr << "<ERROR> ZBDDDG::EnlargeLink(): Memory overflow (";
175
+ cerr << _linkSize << ")\n";
176
+ return 1;
177
+ }
178
+ for(bddword i=0; i<_linkUsed; i++)
179
+ {
180
+ _linkA[i]._ndx = oldArray[i]._ndx;
181
+ _linkA[i]._nxt = oldArray[i]._nxt;
182
+ }
183
+ delete[] oldArray;
184
+ return 0;
185
+ }
186
+
187
+ bddword ZBDDDG::ReferNdx(ZBDD key)
188
+ {
189
+ return _hashWheel[HashIndex(key)];
190
+ }
191
+
192
+ bddword ZBDDDG::NodeUsed() { return _nodeUsed; }
193
+
194
+ ZBDDDG::Node::Node()
195
+ {
196
+ _lkx = ZBDDDG_NIL;
197
+ _f = ZBDD(1);
198
+ _type = ZBDDDG_C0;
199
+ _mark = 0;
200
+ _ndxP = ZBDDDG_NIL;
201
+ }
202
+
203
+ ZBDDDG::Node::Node(ZBDD f, char type)
204
+ {
205
+ _lkx = ZBDDDG_NIL;
206
+ _f = f;
207
+ _type = type;
208
+ _mark = 0;
209
+ _ndxP = ZBDDDG_NIL;
210
+ }
211
+
212
+ int ZBDDDG::PhaseSweep(bddword ndx)
213
+ {
214
+ int fin = 0;
215
+ int inv = 0;
216
+ bddword lkx = _nodeA[ndx]._lkx;
217
+
218
+ switch(_nodeA[ndx]._type)
219
+ {
220
+ case ZBDDDG_P1:
221
+ /* Assertion check*/
222
+ while(lkx != ZBDDDG_NIL)
223
+ {
224
+ if(_nodeA[_linkA[lkx]._ndx]._type == ZBDDDG_P1)
225
+ {
226
+ cerr << "<ERROR> ZBDDDG::PhaseSweep(): Bad structure (P1)\n";
227
+ exit(1);
228
+ }
229
+ lkx = _linkA[lkx]._nxt;
230
+ fin++;
231
+ }
232
+ if(fin != 1)
233
+ {
234
+ cerr << "<ERROR> ZBDDDG::PhaseSweep(): Bad fan-in (P1)\n";
235
+ exit(1);
236
+ }
237
+ break;
238
+ case ZBDDDG_AND:
239
+ /* Assertion check*/
240
+ while(lkx != ZBDDDG_NIL)
241
+ {
242
+ if(_nodeA[_linkA[lkx]._ndx]._type == ZBDDDG_AND)
243
+ {
244
+ cerr << "<ERROR> ZBDDDG::PhaseSweep(): Bad structure (AND)\n";
245
+ exit(1);
246
+ }
247
+ lkx = _linkA[lkx]._nxt;
248
+ fin++;
249
+ }
250
+ if(fin < 2)
251
+ {
252
+ cerr << "<ERROR> ZBDDDG::PhaseSweep(): Bad fan-in (AND)\n";
253
+ exit(1);
254
+ }
255
+ break;
256
+
257
+ case ZBDDDG_OR:
258
+ /* Assertion check*/
259
+ while(lkx != ZBDDDG_NIL)
260
+ {
261
+ if(_nodeA[_linkA[lkx]._ndx]._type == ZBDDDG_OR ||
262
+ _nodeA[_linkA[lkx]._ndx]._type == ZBDDDG_P1)
263
+ {
264
+ cerr << "<ERROR> ZBDDDG::PhaseSweep(): Bad structure (OR)\n";
265
+ exit(1);
266
+ }
267
+ lkx = _linkA[lkx]._nxt;
268
+ fin++;
269
+ }
270
+ if(fin < 2)
271
+ {
272
+ cerr << "<ERROR> ZBDDDG::PhaseSweep(): Bad fan-in (OR)\n";
273
+ // exit(1);
274
+ }
275
+ if((_nodeA[ndx]._f & 1) == 1)
276
+ {
277
+ lkx = _nodeA[ndx]._lkx;
278
+ int chk = 0;
279
+ while(lkx != ZBDDDG_NIL)
280
+ {
281
+ ZBDD f1 = _nodeA[_linkA[lkx]._ndx]._f;
282
+ if((f1 & 1) == 1)
283
+ {
284
+ chk = 1;
285
+ break;
286
+ }
287
+ lkx = _linkA[lkx]._nxt;
288
+ }
289
+ if(chk == 0)
290
+ {
291
+ ZBDD f0 = _nodeA[ndx]._f - 1;
292
+ bddword ndx0 = ReferNdx(f0);
293
+ if(ndx0 == ZBDDDG_NIL)
294
+ {
295
+ ndx0 = NewNdx(_nodeA[ndx]._f - 1, ZBDDDG_OR);
296
+ if(ndx0 == ZBDDDG_NIL) return 1;
297
+ _nodeA[ndx0]._lkx = _nodeA[ndx]._lkx;
298
+ }
299
+ _nodeA[ndx]._lkx = ZBDDDG_NIL;
300
+ _nodeA[ndx]._type = ZBDDDG_P1;
301
+ if(LinkNodes(ndx, ndx0)) return 1;
302
+ }
303
+ }
304
+ break;
305
+
306
+ case ZBDDDG_OTHER:
307
+ /* Assertion check*/
308
+ while(lkx != ZBDDDG_NIL)
309
+ {
310
+ if(_nodeA[_linkA[lkx]._ndx]._type == ZBDDDG_P1)
311
+ {
312
+ cerr << "<ERROR> ZBDDDG::PhaseSweep(): Bad structure (OTHER)\n";
313
+ exit(1);
314
+ }
315
+ lkx = _linkA[lkx]._nxt;
316
+ fin++;
317
+ }
318
+ if(fin < 2)
319
+ {
320
+ cerr << "<ERROR> ZBDDDG::PhaseSweep(): Bad fan-in (OTHER)\n";
321
+ exit(1);
322
+ }
323
+
324
+ if((_nodeA[ndx]._f & 1) == 1)
325
+ {
326
+ lkx = _nodeA[ndx]._lkx;
327
+ int chk = 0;
328
+ while(lkx != ZBDDDG_NIL)
329
+ {
330
+ ZBDD f1 = _nodeA[_linkA[lkx]._ndx]._f;
331
+ if((f1 & 1) == 1 && (Func1(_nodeA[ndx]._f, f1) & 1) == 1)
332
+ {
333
+ chk = 1;
334
+ break;
335
+ }
336
+ lkx = _linkA[lkx]._nxt;
337
+ }
338
+ if(chk == 0)
339
+ {
340
+ ZBDD f0 = _nodeA[ndx]._f - 1;
341
+ bddword ndx0 = ReferNdx(f0);
342
+ if(ndx0 == ZBDDDG_NIL)
343
+ {
344
+ ndx0 = NewNdx(_nodeA[ndx]._f - 1, ZBDDDG_OTHER);
345
+ if(ndx0 == ZBDDDG_NIL) return 1;
346
+ _nodeA[ndx0]._lkx = _nodeA[ndx]._lkx;
347
+ }
348
+ _nodeA[ndx]._lkx = ZBDDDG_NIL;
349
+ _nodeA[ndx]._type = ZBDDDG_P1;
350
+ if(LinkNodes(ndx, ndx0)) return 1;
351
+ }
352
+ }
353
+
354
+ break;
355
+ default:
356
+ cerr << "<ERROR> ZBDDDG::PhaseSweep(): Bad node type\n";
357
+ exit(1);
358
+ }
359
+ return 0;
360
+ }
361
+
362
+ int ZBDDDG::LinkNodes(bddword ndx, bddword ndx2)
363
+ {
364
+ if(ndx == ZBDDDG_NIL || ndx2 == ZBDDDG_NIL)
365
+ {
366
+ cerr << "<ERROR> ZBDDDG::LinkNodes(): Null node\n";
367
+ exit(1);
368
+ }
369
+ bddword lkx = NewLkx(ndx2);
370
+ if(lkx == ZBDDDG_NIL) return 1;
371
+ _linkA[lkx]._nxt = _nodeA[ndx]._lkx;
372
+ _nodeA[ndx]._lkx = lkx;
373
+
374
+ bddword lkx2 = _linkA[lkx]._nxt;
375
+ while(lkx2 != ZBDDDG_NIL)
376
+ {
377
+ bddword ndx3 = _linkA[lkx]._ndx;
378
+ bddword ndx4 = _linkA[lkx2]._ndx;
379
+ ZBDD f = _nodeA[ndx3]._f;
380
+ ZBDD f2 = _nodeA[ndx4]._f;
381
+ if(f.Top() == f2.Top())
382
+ {
383
+ cerr << "<ERROR> ZBDDDG::LinkNodes(): Same VarIndex(";
384
+ cerr << f.Top() << ")\n";
385
+ exit(1);
386
+ }
387
+
388
+ if(f.Top() < f2.Top()) break;
389
+
390
+ _linkA[lkx]._ndx = ndx4;
391
+ _linkA[lkx2]._ndx = ndx3;
392
+
393
+ lkx = lkx2;
394
+ lkx2 = _linkA[lkx2]._nxt;
395
+ }
396
+ return 0;
397
+ }
398
+
399
+ bddword ZBDDDG::Decomp(ZBDD f)
400
+ {
401
+ if(f == 0) return _c0;
402
+ if(f == 1) return _c1;
403
+
404
+ bddword ndx = ReferNdx(f);
405
+ if(ndx != ZBDDDG_NIL) return ndx;
406
+
407
+ int top = f.Top();
408
+ ZBDD f0 = f.OffSet(top);
409
+ ZBDD f1 = f.OnSet0(top);
410
+ bddword ndx0 = Decomp(f0);
411
+ if(ndx0 == ZBDDDG_NIL) return ZBDDDG_NIL;
412
+ bddword ndx1 = Decomp(f1);
413
+ if(ndx1 == ZBDDDG_NIL) return ZBDDDG_NIL;
414
+ //PrintDecomp(f0);
415
+ //PrintDecomp(f1);
416
+ ndx = Merge(f, ndx0, ndx1);
417
+ //PrintDecomp(f); cout << "\n";
418
+
419
+ return ndx;
420
+ }
421
+
422
+ void ZBDDDG::MarkSweep(bddword ndx)
423
+ {
424
+ if(ndx == ZBDDDG_NIL)
425
+ {
426
+ cerr << "<ERROR> ZBDDDG::MarkSweep(): Bad ndx";
427
+ exit(1);
428
+ }
429
+ _nodeA[ndx]._mark = 0;
430
+ bddword lkx = _nodeA[ndx]._lkx;
431
+ while(lkx != ZBDDDG_NIL)
432
+ {
433
+ _nodeA[_linkA[lkx]._ndx]._mark = 0;
434
+ lkx = _linkA[lkx]._nxt;
435
+ }
436
+ }
437
+
438
+ void ZBDDDG::MarkSweepR(bddword ndx)
439
+ {
440
+ if(ndx == ZBDDDG_NIL)
441
+ {
442
+ cerr << "<ERROR> ZBDDDG::MarkSweepR(): Bad ndx";
443
+ exit(1);
444
+ }
445
+ _nodeA[ndx]._mark = 0;
446
+ _nodeA[ndx]._ndxP = ZBDDDG_NIL;
447
+ bddword lkx = _nodeA[ndx]._lkx;
448
+ while(lkx != ZBDDDG_NIL)
449
+ {
450
+ MarkSweepR(_linkA[lkx]._ndx);
451
+ lkx = _linkA[lkx]._nxt;
452
+ }
453
+ }
454
+
455
+ int ZBDDDG::Mark1(bddword ndx)
456
+ {
457
+ if(ndx == ZBDDDG_NIL)
458
+ {
459
+ cerr << "<ERROR> ZBDDDG::Mark1(): Bad ndx";
460
+ exit(1);
461
+ }
462
+ int fin = 0;
463
+ bddword lkx = _nodeA[ndx]._lkx;
464
+ while(lkx != ZBDDDG_NIL)
465
+ {
466
+ bddword ndx1 = _linkA[lkx]._ndx;
467
+ _nodeA[ndx1]._mark = 1;
468
+ fin++;
469
+ lkx = _linkA[lkx]._nxt;
470
+ }
471
+ return fin;
472
+ }
473
+
474
+ void ZBDDDG::Mark2R(bddword ndx)
475
+ {
476
+ if(ndx == ZBDDDG_NIL)
477
+ {
478
+ cerr << "<ERROR> ZBDDDG::Mark2R(): Bad ndx";
479
+ exit(1);
480
+ }
481
+ _nodeA[ndx]._mark++;
482
+ bddword lkx = _nodeA[ndx]._lkx;
483
+ while(lkx != ZBDDDG_NIL)
484
+ {
485
+ Mark2R(_linkA[lkx]._ndx);
486
+ lkx = _linkA[lkx]._nxt;
487
+ }
488
+ }
489
+
490
+ int ZBDDDG::MarkChkR(bddword ndx)
491
+ {
492
+ if(ndx == ZBDDDG_NIL)
493
+ {
494
+ cerr << "<ERROR> ZBDDDG::MarkChkR(): Bad ndx";
495
+ exit(1);
496
+ }
497
+ if(_nodeA[ndx]._mark != 0) return 1;
498
+ bddword lkx = _nodeA[ndx]._lkx;
499
+ while(lkx != ZBDDDG_NIL)
500
+ {
501
+ if(MarkChkR(_linkA[lkx]._ndx)) return 1;
502
+ lkx = _linkA[lkx]._nxt;
503
+ }
504
+ return 0;
505
+ }
506
+
507
+ void ZBDDDG::Mark3R(bddword ndx)
508
+ {
509
+ if(ndx == ZBDDDG_NIL)
510
+ {
511
+ cerr << "<ERROR> ZBDDDG::Mark3R(): Bad ndx";
512
+ exit(1);
513
+ }
514
+ if(_nodeA[ndx]._mark == 2) return;
515
+
516
+ int cnt1 = 0; // not decided.
517
+ int cnt2 = 0; // shared node.
518
+ int cnt3 = 0; // non-shared node.
519
+ int cnt4 = 0; // (possibly) partly shared node.
520
+
521
+ bddword lkx = _nodeA[ndx]._lkx;
522
+ while(lkx != ZBDDDG_NIL)
523
+ {
524
+ bddword ndt = _linkA[lkx]._ndx;
525
+ Mark3R(ndt);
526
+ switch(_nodeA[ndt]._mark)
527
+ {
528
+ case 1:
529
+ if(_nodeA[ndt]._type != ZBDDDG_P1) cnt1++;
530
+ else
531
+ {
532
+ if(_nodeA[_linkA[_nodeA[ndt]._lkx]._ndx]._mark == 2)
533
+ cnt2++;
534
+ else cnt1++;
535
+ }
536
+ break;
537
+ case 2:
538
+ cnt2++;
539
+ break;
540
+ case 3:
541
+ cnt3++;
542
+ break;
543
+ case 4:
544
+ cnt4++;
545
+ break;
546
+ default:
547
+ break;
548
+ }
549
+ lkx = _linkA[lkx]._nxt;
550
+ }
551
+ if(_nodeA[ndx]._type == ZBDDDG_AND || _nodeA[ndx]._type == ZBDDDG_OR)
552
+ {
553
+ if(cnt2 >= 1)
554
+ {
555
+ lkx = _nodeA[ndx]._lkx;
556
+ while(lkx != ZBDDDG_NIL)
557
+ {
558
+ bddword ndt = _linkA[lkx]._ndx;
559
+ _nodeA[ndt]._ndxP = ndx;
560
+ lkx = _linkA[lkx]._nxt;
561
+ }
562
+ _nodeA[ndx]._mark = 4;
563
+ return;
564
+ }
565
+ }
566
+
567
+ if(cnt1 + cnt2 + cnt4 == 0 && _nodeA[ndx]._mark == 1)
568
+ _nodeA[ndx]._mark = 3;
569
+ }
570
+
571
+ bddword ZBDDDG::Mark4R(bddword ndx0, bddword ndx1, bddword ndy0)
572
+ {
573
+ if(ndy0 == ZBDDDG_NIL)
574
+ {
575
+ cerr << "<ERROR> ZBDDDG::Mark4R(): Bad ndx";
576
+ exit(1);
577
+ }
578
+ if(_nodeA[ndy0]._mark == 1) return ZBDDDG_NIL;
579
+ if(ndx0 != ndy0 && MarkChkR(ndy0) == 0)
580
+ {
581
+ if(Func1(_nodeA[ndx0]._f, _nodeA[ndy0]._f) == _nodeA[ndx1]._f)
582
+ {
583
+ _nodeA[ndy0]._mark = 3; // hit at this node.
584
+ return ndy0;
585
+ }
586
+ }
587
+ bddword lkx = _nodeA[ndy0]._lkx;
588
+ while(lkx != ZBDDDG_NIL)
589
+ {
590
+ bddword ndt = _linkA[lkx]._ndx;
591
+ bddword ndh = Mark4R(ndx0, ndx1, ndt);
592
+ if(ndh != ZBDDDG_NIL)
593
+ {
594
+ _nodeA[ndy0]._mark = 2; // hit at a sub-node.
595
+ return ndh;
596
+ }
597
+ lkx = _linkA[lkx]._nxt;
598
+ }
599
+ return ZBDDDG_NIL;
600
+ }
601
+
602
+ bddword ZBDDDG::Mark5R(bddword ndx0, bddword ndx1, bddword ndy0)
603
+ {
604
+ if(ndy0 == ZBDDDG_NIL)
605
+ {
606
+ cerr << "<ERROR> ZBDDDG::Mark5R(): Bad ndx";
607
+ exit(1);
608
+ }
609
+ if(ndx0 != ndy0)
610
+ {
611
+ Mark6R(ndx0, ndy0);
612
+ int fin1 = 0;
613
+ int fin2 = 0;
614
+ bddword lkx = _nodeA[ndx1]._lkx;
615
+ while(lkx != ZBDDDG_NIL)
616
+ {
617
+ bddword ndt = _linkA[lkx]._ndx;
618
+ if(MarkChkR(ndt) != 0) _nodeA[ndt]._mark = 1;
619
+ else fin2++;
620
+ fin1++;
621
+ lkx = _linkA[lkx]._nxt;
622
+ }
623
+ if(fin2 > 0 && fin1 - fin2 > 0)
624
+ {
625
+ ZBDD f1 = 1;
626
+ lkx = _nodeA[ndx1]._lkx;
627
+ while(lkx != ZBDDDG_NIL)
628
+ {
629
+ bddword ndt = _linkA[lkx]._ndx;
630
+ if(_nodeA[ndt]._mark == 1) f1 *= _nodeA[ndt]._f;
631
+ lkx = _linkA[lkx]._nxt;
632
+ }
633
+ if(Func1(_nodeA[ndx0]._f, _nodeA[ndy0]._f) == f1)
634
+ {
635
+ _nodeA[ndy0]._mark = 3; // hit at this node.
636
+ return ndy0;
637
+ }
638
+ }
639
+ MarkSweepR(ndx0);
640
+ MarkSweep(ndx1);
641
+ }
642
+ bddword lkx = _nodeA[ndy0]._lkx;
643
+ while(lkx != ZBDDDG_NIL)
644
+ {
645
+ bddword ndt = _linkA[lkx]._ndx;
646
+ bddword ndh = Mark5R(ndx0, ndx1, ndt);
647
+ if(ndh != ZBDDDG_NIL)
648
+ {
649
+ _nodeA[ndy0]._mark = 2; // hit at a sub-node.
650
+ return ndh;
651
+ }
652
+ lkx = _linkA[lkx]._nxt;
653
+ }
654
+ return ZBDDDG_NIL;
655
+ }
656
+
657
+ void ZBDDDG::Mark6R(bddword ndx, bddword ndy)
658
+ {
659
+ if(ndx == ZBDDDG_NIL || ndy == ZBDDDG_NIL)
660
+ {
661
+ cerr << "<ERROR> ZBDDDG::Mark6R(): Bad ndx";
662
+ exit(1);
663
+ }
664
+ if(ndx == ndy) return;
665
+ _nodeA[ndx]._mark++;
666
+ bddword lkx = _nodeA[ndx]._lkx;
667
+ while(lkx != ZBDDDG_NIL)
668
+ {
669
+ Mark6R(_linkA[lkx]._ndx, ndy);
670
+ lkx = _linkA[lkx]._nxt;
671
+ }
672
+ }
673
+
674
+ bddword ZBDDDG::Merge(ZBDD f, bddword ndx0, bddword ndx1)
675
+ {
676
+ if(ndx0 == ZBDDDG_NIL || ndx1 == ZBDDDG_NIL)
677
+ {
678
+ cerr << "<ERROR> ZBDDDG::Merge(): Null node\n";
679
+ exit(1);
680
+ }
681
+
682
+ //cout << "[Merge]\n";
683
+ int top = f.Top(); // (top > 0)
684
+
685
+ // [LIT] ?
686
+ if(ndx0 == _c0 && ndx1 == _c1)
687
+ {
688
+ //cout << "[LIT]\n";
689
+ bddword ndy = ReferNdx(f);
690
+ if(ndy == ZBDDDG_NIL)
691
+ ndy = NewNdx(f, ZBDDDG_LIT);
692
+ return ndy;
693
+ }
694
+
695
+ // [AND] P0==1, P1==1 ?
696
+ if(ndx0 == ndx1 && ndx0 != _c1)
697
+ {
698
+ //cout << "[AND] P0==1, P1==1\n";
699
+ bddword ndx = Decomp(ZBDD(1).Change(top) + 1);
700
+ if(ndx == ZBDDDG_NIL) return ZBDDDG_NIL;
701
+ bddword ndy = NewNdx(f, ZBDDDG_AND);
702
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
703
+ if(LinkNodes(ndy, ndx)) return ZBDDDG_NIL;
704
+ if(_nodeA[ndx1]._type != ZBDDDG_AND)
705
+ {
706
+ if(LinkNodes(ndy, ndx1)) return ZBDDDG_NIL;
707
+ }
708
+ else
709
+ {
710
+ bddword lkx = _nodeA[ndx1]._lkx;
711
+ while(lkx != ZBDDDG_NIL)
712
+ {
713
+ if(LinkNodes(ndy, _linkA[lkx]._ndx)) return ZBDDDG_NIL;
714
+ lkx = _linkA[lkx]._nxt;
715
+ }
716
+ }
717
+ if(PhaseSweep(ndy)) return ZBDDDG_NIL;
718
+ return ndy;
719
+ }
720
+
721
+ // [AND] P0==0, P1==1 ?
722
+ if(ndx0 == _c0)
723
+ {
724
+ //cout << "[AND] P0==0, P1==1\n";
725
+ bddword ndx = Decomp(ZBDD(1).Change(top));
726
+ if(ndx == ZBDDDG_NIL) return ZBDDDG_NIL;
727
+ bddword ndy = NewNdx(f, ZBDDDG_AND);
728
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
729
+ if(LinkNodes(ndy, ndx)) return ZBDDDG_NIL;
730
+ if(_nodeA[ndx1]._type != ZBDDDG_AND)
731
+ {
732
+ if(LinkNodes(ndy, ndx1)) return ZBDDDG_NIL;
733
+ }
734
+ else
735
+ {
736
+ bddword lkx = _nodeA[ndx1]._lkx;
737
+ while(lkx != ZBDDDG_NIL)
738
+ {
739
+ if(LinkNodes(ndy, _linkA[lkx]._ndx)) return ZBDDDG_NIL;
740
+ lkx = _linkA[lkx]._nxt;
741
+ }
742
+ }
743
+ if(PhaseSweep(ndy)) return ZBDDDG_NIL;
744
+ return ndy;
745
+ }
746
+
747
+ // [OR] P0==0, P1==1 ?
748
+ if(ndx1 == _c1 && _nodeA[ndx0]._type != ZBDDDG_P1)
749
+ {
750
+ //cout << "[OR] P0==0, P1==1\n";
751
+ bddword ndx = Decomp(ZBDD(1).Change(top));
752
+ if(ndx == ZBDDDG_NIL) return ZBDDDG_NIL;
753
+ bddword ndy = NewNdx(f, ZBDDDG_OR);
754
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
755
+ if(LinkNodes(ndy, ndx)) return ZBDDDG_NIL;
756
+ if(_nodeA[ndx0]._type != ZBDDDG_OR)
757
+ {
758
+ if(LinkNodes(ndy, ndx0)) return ZBDDDG_NIL;
759
+ }
760
+ else
761
+ {
762
+ bddword lkx = _nodeA[ndx0]._lkx;
763
+ while(lkx != ZBDDDG_NIL)
764
+ {
765
+ if(LinkNodes(ndy, _linkA[lkx]._ndx)) return ZBDDDG_NIL;
766
+ lkx = _linkA[lkx]._nxt;
767
+ }
768
+ }
769
+ if(PhaseSweep(ndy)) return ZBDDDG_NIL;
770
+ return ndy;
771
+ }
772
+
773
+ // [AND] General or P0==1 or P1==1 ?
774
+ if(_nodeA[ndx0]._type == ZBDDDG_AND &&
775
+ _nodeA[ndx1]._type == ZBDDDG_AND)
776
+ {
777
+ //cout << "[AND] general\n";
778
+ int fin0 = 0;
779
+ int fin1 = 0;
780
+ int fin2 = 0;
781
+
782
+ fin0 = Mark1(ndx0);
783
+ bddword lkx = _nodeA[ndx1]._lkx;
784
+ while(lkx != ZBDDDG_NIL)
785
+ {
786
+ bddword ndt = _linkA[lkx]._ndx;
787
+ if(_nodeA[ndt]._mark == 1)
788
+ {
789
+ fin2++;
790
+ _nodeA[ndt]._mark = 3;
791
+ }
792
+ lkx = _linkA[lkx]._nxt;
793
+ fin1++;
794
+ }
795
+
796
+ if(fin2 > 0)
797
+ {
798
+ bddword ndy0;
799
+ if(fin0 - fin2 > 1)
800
+ {
801
+ ZBDD g = 1;
802
+ lkx = _nodeA[ndx0]._lkx;
803
+ while(lkx != ZBDDDG_NIL)
804
+ {
805
+ bddword ndt = _linkA[lkx]._ndx;
806
+ if(_nodeA[ndt]._mark != 3) g *= _nodeA[ndt]._f;
807
+ lkx = _linkA[lkx]._nxt;
808
+ }
809
+ ndy0 = ReferNdx(g);
810
+ if(ndy0 == ZBDDDG_NIL)
811
+ {
812
+ ndy0 = NewNdx(g, ZBDDDG_AND);
813
+ if(ndy0 == ZBDDDG_NIL) return ZBDDDG_NIL;
814
+ lkx = _nodeA[ndx0]._lkx;
815
+ while(lkx != ZBDDDG_NIL)
816
+ {
817
+ bddword ndt = _linkA[lkx]._ndx;
818
+ if(_nodeA[ndt]._mark != 3)
819
+ if(LinkNodes(ndy0, ndt)) return ZBDDDG_NIL;
820
+ lkx = _linkA[lkx]._nxt;
821
+ }
822
+ }
823
+ }
824
+ else if(fin0 - fin2 == 1)
825
+ {
826
+ lkx = _nodeA[ndx0]._lkx;
827
+ while(lkx != ZBDDDG_NIL)
828
+ {
829
+ bddword ndt = _linkA[lkx]._ndx;
830
+ if(_nodeA[ndt]._mark != 3)
831
+ { ndy0 = ndt; break; }
832
+ lkx = _linkA[lkx]._nxt;
833
+ }
834
+ }
835
+ else ndy0 = _c1;
836
+
837
+ bddword ndy1;
838
+ if(fin1 - fin2 > 1)
839
+ {
840
+ ZBDD g = 1;
841
+ lkx = _nodeA[ndx1]._lkx;
842
+ while(lkx != ZBDDDG_NIL)
843
+ {
844
+ bddword ndt = _linkA[lkx]._ndx;
845
+ if(_nodeA[ndt]._mark != 3) g *= _nodeA[ndt]._f;
846
+ lkx = _linkA[lkx]._nxt;
847
+ }
848
+ ndy1 = ReferNdx(g);
849
+ if(ndy1 == ZBDDDG_NIL)
850
+ {
851
+ ndy1 = NewNdx(g, ZBDDDG_AND);
852
+ if(ndy1 == ZBDDDG_NIL) return ZBDDDG_NIL;
853
+ lkx = _nodeA[ndx1]._lkx;
854
+ while(lkx != ZBDDDG_NIL)
855
+ {
856
+ bddword ndt = _linkA[lkx]._ndx;
857
+ if(_nodeA[ndt]._mark != 3)
858
+ if(LinkNodes(ndy1, ndt)) return ZBDDDG_NIL;
859
+ lkx = _linkA[lkx]._nxt;
860
+ }
861
+ }
862
+ }
863
+ else if(fin1 - fin2 == 1)
864
+ {
865
+ lkx = _nodeA[ndx1]._lkx;
866
+ while(lkx != ZBDDDG_NIL)
867
+ {
868
+ bddword ndt = _linkA[lkx]._ndx;
869
+ if(_nodeA[ndt]._mark != 3)
870
+ { ndy1 = ndt; break; }
871
+ lkx = _linkA[lkx]._nxt;
872
+ }
873
+ }
874
+ else ndy1 = _c1;
875
+
876
+ bddword ndy = NewNdx(f, ZBDDDG_AND);
877
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
878
+ lkx = _nodeA[ndx0]._lkx;
879
+ while(lkx != ZBDDDG_NIL)
880
+ {
881
+ bddword ndt = _linkA[lkx]._ndx;
882
+ if(_nodeA[ndt]._mark == 3)
883
+ if(LinkNodes(ndy, ndt)) return ZBDDDG_NIL;
884
+ lkx = _linkA[lkx]._nxt;
885
+ }
886
+
887
+ MarkSweep(ndx0);
888
+ if(Merge3(ndy, ndy0, ndy1)) return ZBDDDG_NIL;;
889
+ return ndy;
890
+ }
891
+ MarkSweep(ndx0);
892
+ }
893
+
894
+ // [AND] P1==1 (special) ?
895
+ if(_nodeA[ndx0]._type == ZBDDDG_AND)
896
+ {
897
+ //cout << "[AND] P1==1(special)\n";
898
+ int fin0 = 0;
899
+ int fin2 = 0;
900
+ _nodeA[ndx1]._mark = 1;
901
+ bddword lkx = _nodeA[ndx0]._lkx;
902
+ while(lkx != ZBDDDG_NIL)
903
+ {
904
+ bddword ndt = _linkA[lkx]._ndx;
905
+ if(_nodeA[ndt]._mark == 1) fin2++;
906
+ fin0++;
907
+ lkx = _linkA[lkx]._nxt;
908
+ }
909
+
910
+ if(fin2 > 0)
911
+ {
912
+ bddword ndy0;
913
+ if(fin0 > 2)
914
+ {
915
+ ZBDD g = 1;
916
+ lkx = _nodeA[ndx0]._lkx;
917
+ while(lkx != ZBDDDG_NIL)
918
+ {
919
+ bddword ndt = _linkA[lkx]._ndx;
920
+ if(_nodeA[ndt]._mark == 0) g *= _nodeA[ndt]._f;
921
+ lkx = _linkA[lkx]._nxt;
922
+ }
923
+ ndy0 = ReferNdx(g);
924
+ if(ndy0 == ZBDDDG_NIL)
925
+ {
926
+ ndy0 = NewNdx(g, ZBDDDG_AND);
927
+ if(ndy0 == ZBDDDG_NIL) return ZBDDDG_NIL;
928
+ lkx = _nodeA[ndx0]._lkx;
929
+ while(lkx != ZBDDDG_NIL)
930
+ {
931
+ bddword ndt = _linkA[lkx]._ndx;
932
+ if(_nodeA[ndt]._mark == 0)
933
+ if(LinkNodes(ndy0, ndt)) return ZBDDDG_NIL;
934
+ lkx = _linkA[lkx]._nxt;
935
+ }
936
+ }
937
+ }
938
+ else
939
+ {
940
+ lkx = _nodeA[ndx0]._lkx;
941
+ while(lkx != ZBDDDG_NIL)
942
+ {
943
+ bddword ndt = _linkA[lkx]._ndx;
944
+ if(_nodeA[ndt]._mark == 0)
945
+ { ndy0 = ndt; break; }
946
+ lkx = _linkA[lkx]._nxt;
947
+ }
948
+ }
949
+
950
+ bddword ndy = NewNdx(f, ZBDDDG_AND);
951
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
952
+ if(LinkNodes(ndy, ndx1)) return ZBDDDG_NIL;
953
+
954
+ _nodeA[ndx1]._mark = 0;
955
+ if(Merge3(ndy, ndy0, _c1)) return ZBDDDG_NIL;;
956
+ return ndy;
957
+ }
958
+ _nodeA[ndx1]._mark = 0;
959
+ }
960
+
961
+ // [AND] P0==1 (special) ?
962
+ if(_nodeA[ndx1]._type == ZBDDDG_AND)
963
+ {
964
+ //cout << "[AND] P0==1(special)\n";
965
+ int fin1 = 0;
966
+ int fin2 = 0;
967
+ _nodeA[ndx0]._mark = 1;
968
+ bddword lkx = _nodeA[ndx1]._lkx;
969
+ while(lkx != ZBDDDG_NIL)
970
+ {
971
+ bddword ndt = _linkA[lkx]._ndx;
972
+ if(_nodeA[ndt]._mark == 1) fin2++;
973
+ fin1++;
974
+ lkx = _linkA[lkx]._nxt;
975
+ }
976
+
977
+ if(fin2 > 0)
978
+ {
979
+ bddword ndy1;
980
+ if(fin1 > 2)
981
+ {
982
+ ZBDD g = 1;
983
+ lkx = _nodeA[ndx1]._lkx;
984
+ while(lkx != ZBDDDG_NIL)
985
+ {
986
+ bddword ndt = _linkA[lkx]._ndx;
987
+ if(_nodeA[ndt]._mark == 0) g *= _nodeA[ndt]._f;
988
+ lkx = _linkA[lkx]._nxt;
989
+ }
990
+ ndy1 = ReferNdx(g);
991
+ if(ndy1 == ZBDDDG_NIL)
992
+ {
993
+ ndy1 = NewNdx(g, ZBDDDG_AND);
994
+ if(ndy1 == ZBDDDG_NIL) return ZBDDDG_NIL;
995
+ lkx = _nodeA[ndx1]._lkx;
996
+ while(lkx != ZBDDDG_NIL)
997
+ {
998
+ bddword ndt = _linkA[lkx]._ndx;
999
+ if(_nodeA[ndt]._mark == 0)
1000
+ if(LinkNodes(ndy1, ndt)) return ZBDDDG_NIL;
1001
+ lkx = _linkA[lkx]._nxt;
1002
+ }
1003
+ }
1004
+ }
1005
+ else
1006
+ {
1007
+ lkx = _nodeA[ndx1]._lkx;
1008
+ while(lkx != ZBDDDG_NIL)
1009
+ {
1010
+ bddword ndt = _linkA[lkx]._ndx;
1011
+ if(_nodeA[ndt]._mark == 0)
1012
+ { ndy1 = ndt; break; }
1013
+ lkx = _linkA[lkx]._nxt;
1014
+ }
1015
+ }
1016
+
1017
+ bddword ndy = NewNdx(f, ZBDDDG_AND);
1018
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
1019
+ if(LinkNodes(ndy, ndx0)) return ZBDDDG_NIL;
1020
+
1021
+ _nodeA[ndx0]._mark = 0;
1022
+ if(Merge3(ndy, _c1, ndy1)) return ZBDDDG_NIL;;
1023
+ return ndy;
1024
+ }
1025
+ _nodeA[ndx0]._mark = 0;
1026
+ }
1027
+
1028
+ // [OR] general or P0==0 ?
1029
+ bddword ndx00 = ndx0;
1030
+ if(_nodeA[ndx00]._type == ZBDDDG_P1)
1031
+ ndx00 = _linkA[_nodeA[ndx00]._lkx]._ndx;
1032
+
1033
+ if(_nodeA[ndx00]._type == ZBDDDG_OR)
1034
+ {
1035
+ //cout << "[OR] (general)\n";
1036
+ int fin0 = 0;
1037
+ int fin2 = 0;
1038
+ Mark2R(ndx1);
1039
+ bddword lkx = _nodeA[ndx00]._lkx;
1040
+ while(lkx != ZBDDDG_NIL)
1041
+ {
1042
+ bddword ndt = _linkA[lkx]._ndx;
1043
+ if(MarkChkR(ndt) != 0) _nodeA[ndt]._mark = 1;
1044
+ else fin2++;
1045
+ fin0++;
1046
+ lkx = _linkA[lkx]._nxt;
1047
+ }
1048
+ if(fin2 > 0)
1049
+ {
1050
+ bddword ndy0;
1051
+ if(fin0 - fin2 > 1)
1052
+ {
1053
+ ZBDD g = 0;
1054
+ lkx = _nodeA[ndx00]._lkx;
1055
+ while(lkx != ZBDDDG_NIL)
1056
+ {
1057
+ bddword ndt = _linkA[lkx]._ndx;
1058
+ if(_nodeA[ndt]._mark == 1) g += _nodeA[ndt]._f;
1059
+ lkx = _linkA[lkx]._nxt;
1060
+ }
1061
+ ndy0 = ReferNdx(g);
1062
+ if(ndy0 == ZBDDDG_NIL)
1063
+ {
1064
+ ndy0 = NewNdx(g, ZBDDDG_OR);
1065
+ if(ndy0 == ZBDDDG_NIL) return ZBDDDG_NIL;
1066
+ lkx = _nodeA[ndx00]._lkx;
1067
+ while(lkx != ZBDDDG_NIL)
1068
+ {
1069
+ bddword ndt = _linkA[lkx]._ndx;
1070
+ if(_nodeA[ndt]._mark == 1)
1071
+ if(LinkNodes(ndy0, ndt)) return ZBDDDG_NIL;
1072
+ lkx = _linkA[lkx]._nxt;
1073
+ }
1074
+ }
1075
+ }
1076
+ else if(fin0 - fin2 == 1)
1077
+ {
1078
+ lkx = _nodeA[ndx00]._lkx;
1079
+ while(lkx != ZBDDDG_NIL)
1080
+ {
1081
+ bddword ndt = _linkA[lkx]._ndx;
1082
+ if(_nodeA[ndt]._mark == 1)
1083
+ { ndy0 = ndt; break; }
1084
+ lkx = _linkA[lkx]._nxt;
1085
+ }
1086
+ }
1087
+ else ndy0 = _c0;
1088
+
1089
+ if((f & 1) == 1)
1090
+ {
1091
+ ZBDD g0 = _nodeA[ndy0]._f + 1;
1092
+ bddword ndy00 = ReferNdx(g0);
1093
+ if(ndy00 == ZBDDDG_NIL)
1094
+ {
1095
+ ndy00 = NewNdx(g0, ZBDDDG_P1);
1096
+ if(ndy00 == ZBDDDG_NIL) return ZBDDDG_NIL;
1097
+ if(LinkNodes(ndy00, ndy0)) return ZBDDDG_NIL;
1098
+ }
1099
+ ndy0 = ndy00;
1100
+ }
1101
+
1102
+ bddword ndy = NewNdx(f, ZBDDDG_OR);
1103
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
1104
+ lkx = _nodeA[ndx00]._lkx;
1105
+ while(lkx != ZBDDDG_NIL)
1106
+ {
1107
+ bddword ndt = _linkA[lkx]._ndx;
1108
+ if(_nodeA[ndt]._mark == 0)
1109
+ if(LinkNodes(ndy, ndt)) return ZBDDDG_NIL;
1110
+ lkx = _linkA[lkx]._nxt;
1111
+ }
1112
+
1113
+ MarkSweepR(ndx1);
1114
+ MarkSweep(ndx00);
1115
+ if(Merge3(ndy, ndy0, ndx1)) return ZBDDDG_NIL;
1116
+ return ndy;
1117
+ }
1118
+
1119
+ MarkSweepR(ndx1);
1120
+ MarkSweep(ndx00);
1121
+ }
1122
+
1123
+ // [OR] P0==0 (special) ?
1124
+ if(_nodeA[ndx00]._type != ZBDDDG_OR)
1125
+ {
1126
+ //cout << "[OR] P0==0 (special)\n";
1127
+ Mark2R(ndx1);
1128
+ if(MarkChkR(ndx00) == 0)
1129
+ {
1130
+ bddword ndy = NewNdx(f, ZBDDDG_OR);
1131
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
1132
+ if(LinkNodes(ndy, ndx00)) return ZBDDDG_NIL;
1133
+
1134
+ MarkSweepR(ndx1);
1135
+ if(Merge3(ndy, _c0, ndx1)) return ZBDDDG_NIL;;
1136
+ return ndy;
1137
+ }
1138
+ MarkSweepR(ndx1);
1139
+ }
1140
+
1141
+ // [OTHER] P1==1 ?
1142
+ if(_nodeA[ndx00]._type == ZBDDDG_OTHER)
1143
+ {
1144
+ //cout << "[OTHER] P1==1\n";
1145
+ Mark2R(ndx1);
1146
+ bddword ndh = Mark4R(ndx0, ndx1, ndx0);
1147
+ if(ndh != ZBDDDG_NIL)
1148
+ {
1149
+ bddword ndy = AppendR(ndx0, top, ndh, _c1);
1150
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
1151
+ if(PhaseSweep(ndy)) return ZBDDDG_NIL;
1152
+ MarkSweepR(ndx0);
1153
+ MarkSweepR(ndx1);
1154
+ return ndy;
1155
+ }
1156
+ MarkSweepR(ndx0);
1157
+ MarkSweepR(ndx1);
1158
+ }
1159
+
1160
+ // [OTHER] general ?
1161
+ if(_nodeA[ndx00]._type == ZBDDDG_OTHER &&
1162
+ _nodeA[ndx1]._type == ZBDDDG_AND)
1163
+ {
1164
+ //cout << "[OTHER] general\n";
1165
+ bddword ndh = Mark5R(ndx0, ndx1, ndx0);
1166
+ if(ndh != ZBDDDG_NIL)
1167
+ {
1168
+ bddword ndy1 = _c1;
1169
+ int fin1 = 0;
1170
+ int fin2 = 0;
1171
+ ZBDD g = 1;
1172
+ bddword lkx = _nodeA[ndx1]._lkx;
1173
+ while(lkx != ZBDDDG_NIL)
1174
+ {
1175
+ bddword ndt = _linkA[lkx]._ndx;
1176
+ fin1++;
1177
+ if(_nodeA[ndt]._mark == 0)
1178
+ {
1179
+ fin2++;
1180
+ g *= _nodeA[ndt]._f;
1181
+ ndy1 = ndt;
1182
+ }
1183
+ lkx = _linkA[lkx]._nxt;
1184
+ }
1185
+ if(fin2 >= 2)
1186
+ {
1187
+ ndy1 = ReferNdx(g);
1188
+ if(ndy1 == ZBDDDG_NIL)
1189
+ {
1190
+ ndy1 = NewNdx(g, ZBDDDG_AND);
1191
+ if(ndy1 == ZBDDDG_NIL) return ZBDDDG_NIL;
1192
+ lkx = _nodeA[ndx1]._lkx;
1193
+ while(lkx != ZBDDDG_NIL)
1194
+ {
1195
+ bddword ndt = _linkA[lkx]._ndx;
1196
+ if(_nodeA[ndt]._mark == 0)
1197
+ if(LinkNodes(ndy1, ndt)) return ZBDDDG_NIL;
1198
+ lkx = _linkA[lkx]._nxt;
1199
+ }
1200
+ }
1201
+ }
1202
+
1203
+ ZBDD f0 = _nodeA[ndx0]._f;
1204
+ if(Func1(f0, ndh) - f0 == 0)
1205
+ {
1206
+ ZBDD g0 = _nodeA[ndh]._f + 1;
1207
+ bddword ndh0 = ReferNdx(g0);
1208
+ if(ndh0 == ZBDDDG_NIL)
1209
+ {
1210
+ ndh0 = NewNdx(g0, ZBDDDG_P1);
1211
+ if(ndh0 == ZBDDDG_NIL) return ZBDDDG_NIL;
1212
+ if(LinkNodes(ndh0, ndh)) return ZBDDDG_NIL;
1213
+ }
1214
+ ndh = ndh0;
1215
+ }
1216
+
1217
+ bddword ndy = AppendR(ndx0, top, ndh, ndy1);
1218
+ MarkSweepR(ndx0);
1219
+ MarkSweep(ndx1);
1220
+ return ndy;
1221
+ }
1222
+ MarkSweepR(ndx0);
1223
+ MarkSweep(ndx1);
1224
+ }
1225
+
1226
+ // [P1] ?
1227
+ if(_nodeA[ndx0]._type == ZBDDDG_P1)
1228
+ {
1229
+ //cout << "[P1]\n";
1230
+ bddword ndy = NewNdx(f, ZBDDDG_P1);
1231
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
1232
+ bddword ndy0 = ReferNdx(f - 1);
1233
+ if(ndy0 == ZBDDDG_NIL)
1234
+ ndy0 = Merge(f - 1, _linkA[_nodeA[ndx0]._lkx]._ndx, ndx1);
1235
+ if(LinkNodes(ndy, ndy0)) return ZBDDDG_NIL;
1236
+ return ndy;
1237
+ }
1238
+
1239
+ // [OTHER] P0==0 ?
1240
+ if(_nodeA[ndx0]._type == ZBDDDG_OTHER
1241
+ && _nodeA[ndx1]._type == ZBDDDG_AND)
1242
+ {
1243
+ //cout << "[OTHER] P0==0\n";
1244
+ Mark2R(ndx0);
1245
+
1246
+ int fin1 = 0;
1247
+ int fin2 = 0;
1248
+ bddword lkx = _nodeA[ndx1]._lkx;
1249
+ while(lkx != ZBDDDG_NIL)
1250
+ {
1251
+ bddword ndt = _linkA[lkx]._ndx;
1252
+ if(MarkChkR(ndt) != 0) _nodeA[ndt]._mark = 1;
1253
+ else fin2++;
1254
+ fin1++;
1255
+ lkx = _linkA[lkx]._nxt;
1256
+ }
1257
+ if(fin2 > 0 && fin1 - fin2 > 0)
1258
+ {
1259
+ bddword ndy1;
1260
+ if(fin2 >= 2)
1261
+ {
1262
+ ZBDD g = 1;
1263
+ lkx = _nodeA[ndx1]._lkx;
1264
+ while(lkx != ZBDDDG_NIL)
1265
+ {
1266
+ bddword ndt = _linkA[lkx]._ndx;
1267
+ if(_nodeA[ndt]._mark == 0) g *= _nodeA[ndt]._f;
1268
+ lkx = _linkA[lkx]._nxt;
1269
+ }
1270
+ ndy1 = ReferNdx(g);
1271
+ if(ndy1 == ZBDDDG_NIL)
1272
+ {
1273
+ ndy1 = NewNdx(g, ZBDDDG_AND);
1274
+ if(ndy1 == ZBDDDG_NIL) return ZBDDDG_NIL;
1275
+ lkx = _nodeA[ndx1]._lkx;
1276
+ while(lkx != ZBDDDG_NIL)
1277
+ {
1278
+ bddword ndt = _linkA[lkx]._ndx;
1279
+ if(_nodeA[ndt]._mark == 0)
1280
+ if(LinkNodes(ndy1, ndt)) return ZBDDDG_NIL;
1281
+ lkx = _linkA[lkx]._nxt;
1282
+ }
1283
+ }
1284
+ }
1285
+ else // fin2 == 1
1286
+ {
1287
+ lkx = _nodeA[ndx1]._lkx;
1288
+ while(lkx != ZBDDDG_NIL)
1289
+ {
1290
+ bddword ndt = _linkA[lkx]._ndx;
1291
+ if(_nodeA[ndt]._mark == 0)
1292
+ { ndy1 = ndt; break; }
1293
+ lkx = _linkA[lkx]._nxt;
1294
+ }
1295
+ }
1296
+
1297
+ bddword ndy2;
1298
+ if(fin1 - fin2 >= 2)
1299
+ {
1300
+ ZBDD g = 1;
1301
+ lkx = _nodeA[ndx1]._lkx;
1302
+ while(lkx != ZBDDDG_NIL)
1303
+ {
1304
+ bddword ndt = _linkA[lkx]._ndx;
1305
+ if(_nodeA[ndt]._mark == 1) g *= _nodeA[ndt]._f;
1306
+ lkx = _linkA[lkx]._nxt;
1307
+ }
1308
+ ndy2 = ReferNdx(g);
1309
+ if(ndy2 == ZBDDDG_NIL)
1310
+ {
1311
+ ndy2 = NewNdx(g, ZBDDDG_AND);
1312
+ if(ndy2 == ZBDDDG_NIL) return ZBDDDG_NIL;
1313
+ lkx = _nodeA[ndx1]._lkx;
1314
+ while(lkx != ZBDDDG_NIL)
1315
+ {
1316
+ bddword ndt = _linkA[lkx]._ndx;
1317
+ if(_nodeA[ndt]._mark == 1)
1318
+ if(LinkNodes(ndy2, ndt)) return ZBDDDG_NIL;
1319
+ lkx = _linkA[lkx]._nxt;
1320
+ }
1321
+ }
1322
+ }
1323
+ else // fin1 - fin2 == 1
1324
+ {
1325
+ lkx = _nodeA[ndx1]._lkx;
1326
+ while(lkx != ZBDDDG_NIL)
1327
+ {
1328
+ bddword ndt = _linkA[lkx]._ndx;
1329
+ if(_nodeA[ndt]._mark == 1)
1330
+ { ndy2 = ndt; break; }
1331
+ lkx = _linkA[lkx]._nxt;
1332
+ }
1333
+ }
1334
+
1335
+ MarkSweepR(ndx0);
1336
+ MarkSweepR(ndy2);
1337
+ Mark2R(ndx0);
1338
+ Mark2R(ndy2);
1339
+ Mark3R(ndx0);
1340
+ Mark3R(ndy2);
1341
+
1342
+ bddword ndy = NewNdx(f, ZBDDDG_OTHER);
1343
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
1344
+ if(LinkNodesC3(ndy, ndx0)) return ZBDDDG_NIL;
1345
+ if(LinkNodesC3(ndy, ndy2)) return ZBDDDG_NIL;
1346
+ if(PhaseSweep(ndy)) return ZBDDDG_NIL;
1347
+ MarkSweepR(ndx0);
1348
+ MarkSweepR(ndy2);
1349
+ if(Merge3(ndy, _c0, ndy1)) return ZBDDDG_NIL;;
1350
+ return ndy;
1351
+ }
1352
+ MarkSweepR(ndx0);
1353
+ }
1354
+
1355
+ // [OTHER] P1==1, P0==0 ?
1356
+ //cout << "[OTHER] (default)\n";
1357
+ MarkSweepR(ndx0);
1358
+ MarkSweepR(ndx1);
1359
+ Mark2R(ndx0);
1360
+ Mark2R(ndx1);
1361
+ Mark3R(ndx0);
1362
+ Mark3R(ndx1);
1363
+ bddword ndx = Decomp(ZBDD(1).Change(top));
1364
+ if(ndx == ZBDDDG_NIL) return ZBDDDG_NIL;
1365
+
1366
+ bddword ndy = NewNdx(f, ZBDDDG_OTHER);
1367
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
1368
+ if(LinkNodes(ndy, ndx)) return ZBDDDG_NIL;
1369
+ if(LinkNodesC3(ndy, ndx0)) return ZBDDDG_NIL;
1370
+ if(LinkNodesC3(ndy, ndx1)) return ZBDDDG_NIL;
1371
+ if(PhaseSweep(ndy)) return ZBDDDG_NIL;
1372
+ MarkSweepR(ndx0);
1373
+ MarkSweepR(ndx1);
1374
+ return ndy;
1375
+ }
1376
+
1377
+ bddword ZBDDDG::AppendR(bddword ndx, int top, bddword ndy0, bddword ndy1)
1378
+ {
1379
+ ZBDD f = _nodeA[ndx]._f;
1380
+ ZBDD h = _nodeA[ndy0]._f;
1381
+ ZBDD g = f + Func1(f, h) * _nodeA[ndy1]._f.Change(top);
1382
+ bddword ndy = ReferNdx(g);
1383
+ if(ndy != ZBDDDG_NIL) return ndy;
1384
+ ndy = NewNdx(g, _nodeA[ndx]._type);
1385
+ if(ndy == ZBDDDG_NIL) return ZBDDDG_NIL;
1386
+ int hit = 0;
1387
+ bddword lkx = _nodeA[ndx]._lkx;
1388
+ while(lkx != ZBDDDG_NIL)
1389
+ {
1390
+ bddword ndt = _linkA[lkx]._ndx;
1391
+ if(_nodeA[ndt]._mark <= 1)
1392
+ {
1393
+ if(LinkNodes(ndy, ndt)) return ZBDDDG_NIL;
1394
+ }
1395
+ else if(_nodeA[ndt]._mark == 2)
1396
+ {
1397
+ bddword ndr = AppendR(ndt, top, ndy0, ndy1);
1398
+ if(ndr == ZBDDDG_NIL) return ZBDDDG_NIL;
1399
+ if(LinkNodes(ndy, ndr)) return ZBDDDG_NIL;
1400
+ }
1401
+ else hit = 1;
1402
+ lkx = _linkA[lkx]._nxt;
1403
+ }
1404
+ if(hit)
1405
+ {
1406
+ if(Merge3(ndy, ndy0, ndy1)) return ZBDDDG_NIL;
1407
+ }
1408
+ if(PhaseSweep(ndy)) return ZBDDDG_NIL;
1409
+ return ndy;
1410
+ }
1411
+
1412
+ int ZBDDDG::LinkNodesC3(bddword ndy, bddword ndx)
1413
+ {
1414
+ bddword lkx;
1415
+ switch(_nodeA[ndx]._mark)
1416
+ {
1417
+ case 1:
1418
+ lkx = _nodeA[ndx]._lkx;
1419
+ while(lkx != ZBDDDG_NIL)
1420
+ {
1421
+ if(LinkNodesC3(ndy, _linkA[lkx]._ndx)) return 1;
1422
+ lkx = _linkA[lkx]._nxt;
1423
+ }
1424
+ break;
1425
+ case 2:
1426
+ if(_nodeA[ndx]._type == ZBDDDG_P1)
1427
+ {
1428
+ if(LinkNodesC3(ndy, _linkA[_nodeA[ndx]._lkx]._ndx)) return 1;
1429
+ break;
1430
+ }
1431
+ if(LinkNodes(ndy, ndx)) return 1;
1432
+ _nodeA[ndx]._mark = 9;
1433
+ break;
1434
+ case 3:
1435
+ if(_nodeA[ndx]._type == ZBDDDG_P1)
1436
+ {
1437
+ if(LinkNodesC3(ndy, _linkA[_nodeA[ndx]._lkx]._ndx)) return 1;
1438
+ break;
1439
+ }
1440
+ if(LinkNodes(ndy, ndx)) return 1;
1441
+ break;
1442
+ case 4:
1443
+ {
1444
+ lkx = _nodeA[ndx]._lkx;
1445
+ while(lkx != ZBDDDG_NIL)
1446
+ {
1447
+ bddword ndt = _linkA[lkx]._ndx;
1448
+ bddword ndxP = _nodeA[ndt]._ndxP;
1449
+ if(ndxP != ZBDDDG_NIL && ndxP != ndx)
1450
+ {
1451
+ if(_nodeA[ndxP]._type == ZBDDDG_AND &&
1452
+ _nodeA[ndx]._type == ZBDDDG_AND )
1453
+ {
1454
+ ZBDD g = 1;
1455
+ int fin = 0;
1456
+ bddword lkx2 = lkx;
1457
+ while(lkx2 != ZBDDDG_NIL)
1458
+ {
1459
+ bddword ndt2 = _linkA[lkx2]._ndx;
1460
+ if(ndxP == _nodeA[ndt2]._ndxP)
1461
+ {
1462
+ g *= _nodeA[ndt2]._f;
1463
+ fin++;
1464
+ }
1465
+ lkx2 = _linkA[lkx2]._nxt;
1466
+ }
1467
+ if(fin >= 2)
1468
+ {
1469
+ bddword ndy0 = ReferNdx(g);
1470
+ if(ndy0 == ZBDDDG_NIL)
1471
+ {
1472
+ ndy0 = NewNdx(g, ZBDDDG_AND);
1473
+ if(ndy0 == ZBDDDG_NIL) return 1;
1474
+ lkx2 = lkx;
1475
+ while(lkx2 != ZBDDDG_NIL)
1476
+ {
1477
+ bddword ndt2 = _linkA[lkx2]._ndx;
1478
+ if(ndxP == _nodeA[ndt2]._ndxP)
1479
+ {
1480
+ if(LinkNodes(ndy0, ndt2)) return 1;
1481
+ }
1482
+ lkx2 = _linkA[lkx2]._nxt;
1483
+ }
1484
+ }
1485
+ if(LinkNodes(ndy, ndy0)) return 1;
1486
+
1487
+ lkx2 = lkx;
1488
+ while(lkx2 != ZBDDDG_NIL)
1489
+ {
1490
+ bddword ndt2 = _linkA[lkx2]._ndx;
1491
+ if(ndxP == _nodeA[ndt2]._ndxP)
1492
+ _nodeA[ndt2]._mark = 9;
1493
+ lkx2 = _linkA[lkx2]._nxt;
1494
+ }
1495
+ }
1496
+ lkx2 = lkx;
1497
+ while(lkx2 != ZBDDDG_NIL)
1498
+ {
1499
+ bddword ndt2 = _linkA[lkx2]._ndx;
1500
+ if(ndxP == _nodeA[ndt2]._ndxP)
1501
+ _nodeA[ndt2]._ndxP = ZBDDDG_NIL;
1502
+ lkx2 = _linkA[lkx2]._nxt;
1503
+ }
1504
+ }
1505
+
1506
+ if(_nodeA[ndxP]._type == ZBDDDG_OR &&
1507
+ _nodeA[ndx]._type == ZBDDDG_OR )
1508
+ {
1509
+ ZBDD g = 0;
1510
+ int fin = 0;
1511
+ bddword lkx2 = lkx;
1512
+ while(lkx2 != ZBDDDG_NIL)
1513
+ {
1514
+ bddword ndt2 = _linkA[lkx2]._ndx;
1515
+ if(ndxP == _nodeA[ndt2]._ndxP)
1516
+ {
1517
+ g += _nodeA[ndt2]._f;
1518
+ fin++;
1519
+ }
1520
+ lkx2 = _linkA[lkx2]._nxt;
1521
+ }
1522
+ if(fin >= 2)
1523
+ {
1524
+ bddword ndy0 = ReferNdx(g);
1525
+ if(ndy0 == ZBDDDG_NIL)
1526
+ {
1527
+ ndy0 = NewNdx(g, ZBDDDG_OR);
1528
+ if(ndy0 == ZBDDDG_NIL) return 1;
1529
+ lkx2 = lkx;
1530
+ while(lkx2 != ZBDDDG_NIL)
1531
+ {
1532
+ bddword ndt2 = _linkA[lkx2]._ndx;
1533
+ if(ndxP == _nodeA[ndt2]._ndxP)
1534
+ if(LinkNodes(ndy0, ndt2)) return 1;
1535
+ lkx2 = _linkA[lkx2]._nxt;
1536
+ }
1537
+ }
1538
+ if(LinkNodes(ndy, ndy0)) return 1;
1539
+
1540
+ lkx2 = lkx;
1541
+ while(lkx2 != ZBDDDG_NIL)
1542
+ {
1543
+ bddword ndt2 = _linkA[lkx2]._ndx;
1544
+ if(ndxP == _nodeA[ndt2]._ndxP)
1545
+ _nodeA[ndt2]._mark = 9;
1546
+ lkx2 = _linkA[lkx2]._nxt;
1547
+ }
1548
+ }
1549
+ lkx2 = lkx;
1550
+ while(lkx2 != ZBDDDG_NIL)
1551
+ {
1552
+ bddword ndt2 = _linkA[lkx2]._ndx;
1553
+ if(ndxP == _nodeA[ndt2]._ndxP)
1554
+ _nodeA[ndt2]._ndxP = ZBDDDG_NIL;
1555
+ lkx2 = _linkA[lkx2]._nxt;
1556
+ }
1557
+ }
1558
+ }
1559
+ lkx = _linkA[lkx]._nxt;
1560
+ }
1561
+
1562
+ if(_nodeA[ndx]._type == ZBDDDG_AND)
1563
+ {
1564
+ ZBDD g = 1;
1565
+ int fin = 0;
1566
+ lkx = _nodeA[ndx]._lkx;
1567
+ while(lkx != ZBDDDG_NIL)
1568
+ {
1569
+ bddword ndt = _linkA[lkx]._ndx;
1570
+ if(_nodeA[ndt]._mark == 3)
1571
+ {
1572
+ g *= _nodeA[ndt]._f;
1573
+ fin++;
1574
+ }
1575
+ lkx = _linkA[lkx]._nxt;
1576
+ }
1577
+ if(fin >= 2)
1578
+ {
1579
+ bddword ndy0 = ReferNdx(g);
1580
+ if(ndy0 == ZBDDDG_NIL)
1581
+ {
1582
+ ndy0 = NewNdx(g, ZBDDDG_AND);
1583
+ if(ndy0 == ZBDDDG_NIL) return 1;
1584
+ lkx = _nodeA[ndx]._lkx;
1585
+ while(lkx != ZBDDDG_NIL)
1586
+ {
1587
+ bddword ndt = _linkA[lkx]._ndx;
1588
+ if(_nodeA[ndt]._mark == 3)
1589
+ if(LinkNodes(ndy0, ndt)) return 1;
1590
+ lkx = _linkA[lkx]._nxt;
1591
+ }
1592
+ }
1593
+ if(LinkNodes(ndy, ndy0)) return 1;
1594
+ lkx = _nodeA[ndx]._lkx;
1595
+ while(lkx != ZBDDDG_NIL)
1596
+ {
1597
+ bddword ndt = _linkA[lkx]._ndx;
1598
+ if(_nodeA[ndt]._mark == 3) _nodeA[ndt]._mark = 9;
1599
+ lkx = _linkA[lkx]._nxt;
1600
+ }
1601
+ }
1602
+ }
1603
+
1604
+
1605
+ if(_nodeA[ndx]._type == ZBDDDG_OR)
1606
+ {
1607
+ ZBDD g = 0;
1608
+ int fin = 0;
1609
+ lkx = _nodeA[ndx]._lkx;
1610
+ while(lkx != ZBDDDG_NIL)
1611
+ {
1612
+ bddword ndt = _linkA[lkx]._ndx;
1613
+ if(_nodeA[ndt]._mark == 3)
1614
+ {
1615
+ g += _nodeA[ndt]._f;
1616
+ fin++;
1617
+ }
1618
+ lkx = _linkA[lkx]._nxt;
1619
+ }
1620
+ if(fin >= 2)
1621
+ {
1622
+ bddword ndy0 = ReferNdx(g);
1623
+ if(ndy0 == ZBDDDG_NIL)
1624
+ {
1625
+ ndy0 = NewNdx(g, ZBDDDG_OR);
1626
+ if(ndy0 == ZBDDDG_NIL) return 1;
1627
+ lkx = _nodeA[ndx]._lkx;
1628
+ while(lkx != ZBDDDG_NIL)
1629
+ {
1630
+ bddword ndt = _linkA[lkx]._ndx;
1631
+ if(_nodeA[ndt]._mark == 3)
1632
+ if(LinkNodes(ndy0, ndt)) return 1;
1633
+ lkx = _linkA[lkx]._nxt;
1634
+ }
1635
+ }
1636
+ if(LinkNodes(ndy, ndy0)) return 1;
1637
+ lkx = _nodeA[ndx]._lkx;
1638
+ while(lkx != ZBDDDG_NIL)
1639
+ {
1640
+ bddword ndt = _linkA[lkx]._ndx;
1641
+ if(_nodeA[ndt]._mark == 3) _nodeA[ndt]._mark = 9;
1642
+ lkx = _linkA[lkx]._nxt;
1643
+ }
1644
+ }
1645
+ }
1646
+
1647
+ }
1648
+
1649
+ lkx = _nodeA[ndx]._lkx;
1650
+ while(lkx != ZBDDDG_NIL)
1651
+ {
1652
+ if(LinkNodesC3(ndy, _linkA[lkx]._ndx)) return 1;
1653
+ lkx = _linkA[lkx]._nxt;
1654
+ }
1655
+ break;
1656
+ case 9:
1657
+ break;
1658
+ default:
1659
+ cerr << "<ERROR> ZBDDDG::LinkNodesC3(): wrong case (";
1660
+ cerr << _nodeA[ndx]._mark << ")\n";
1661
+ exit(1);
1662
+ }
1663
+ return 0;
1664
+ }
1665
+
1666
+ ZBDD ZBDDDG::Func0(ZBDD f, ZBDD g)
1667
+ {
1668
+ if(g == 1)
1669
+ {
1670
+ cerr << "<ERROR> ZBDDDG::Func0: g == 1";
1671
+ exit(1);
1672
+ }
1673
+ ZBDD h = f;
1674
+ while(g != 0)
1675
+ {
1676
+ int top = g.Top();
1677
+ ZBDD g0 = g.OffSet(top);
1678
+ if(g0 != 1)
1679
+ {
1680
+ g = g0;
1681
+ h = h.OffSet(top);
1682
+ }
1683
+ else
1684
+ {
1685
+ g = g.OnSet0(top);
1686
+ h = h.OnSet0(top);
1687
+ }
1688
+ }
1689
+ return h;
1690
+ }
1691
+
1692
+ ZBDD ZBDDDG::Func1(ZBDD f, ZBDD g)
1693
+ {
1694
+ if(g == 0)
1695
+ {
1696
+ cerr << "<ERROR> ZBDDDG::Func1: g == 0";
1697
+ exit(1);
1698
+ }
1699
+ ZBDD h = f;
1700
+ while(g != 1)
1701
+ {
1702
+ int top = g.Top();
1703
+ g = g.OnSet0(top);
1704
+ h = h.OnSet0(top);
1705
+ }
1706
+ return h;
1707
+ }
1708
+
1709
+ int ZBDDDG::Merge3(bddword ndy, bddword ndy0, bddword ndy1)
1710
+ {
1711
+ //cout << "[Merge3]\n";
1712
+ int top = _nodeA[ndy]._f.Top();
1713
+ ZBDD h0 = _nodeA[ndy0]._f;
1714
+ ZBDD h1 = _nodeA[ndy1]._f;
1715
+ ZBDD h = h0 + h1.Change(top);
1716
+ bddword ndx = ReferNdx(h);
1717
+ if(ndx == ZBDDDG_NIL) ndx = Merge(h, ndy0, ndy1);
1718
+ if(ndx == ZBDDDG_NIL) return 1;
1719
+ switch(_nodeA[ndy]._type)
1720
+ {
1721
+ case ZBDDDG_AND:
1722
+ if(_nodeA[ndx]._type == ZBDDDG_AND)
1723
+ {
1724
+ bddword lkx = _nodeA[ndx]._lkx;
1725
+ while(lkx != ZBDDDG_NIL)
1726
+ {
1727
+ if(LinkNodes(ndy, _linkA[lkx]._ndx)) return ZBDDDG_NIL;
1728
+ lkx = _linkA[lkx]._nxt;
1729
+ }
1730
+ }
1731
+ else if(LinkNodes(ndy, ndx)) return ZBDDDG_NIL;
1732
+ break;
1733
+ case ZBDDDG_OR:
1734
+ if(_nodeA[ndx]._type == ZBDDDG_P1)
1735
+ ndx = _linkA[_nodeA[ndx]._lkx]._ndx;
1736
+ if(_nodeA[ndx]._type == ZBDDDG_OR)
1737
+ {
1738
+ bddword lkx = _nodeA[ndx]._lkx;
1739
+ while(lkx != ZBDDDG_NIL)
1740
+ {
1741
+ if(LinkNodes(ndy, _linkA[lkx]._ndx)) return ZBDDDG_NIL;
1742
+ lkx = _linkA[lkx]._nxt;
1743
+ }
1744
+ }
1745
+ else if(LinkNodes(ndy, ndx)) return ZBDDDG_NIL;
1746
+ break;
1747
+ case ZBDDDG_OTHER:
1748
+ if(_nodeA[ndx]._type == ZBDDDG_P1)
1749
+ ndx = _linkA[_nodeA[ndx]._lkx]._ndx;
1750
+ if(LinkNodes(ndy, ndx)) return ZBDDDG_NIL;
1751
+ break;
1752
+ default:
1753
+ if(LinkNodes(ndy, ndx)) return ZBDDDG_NIL;
1754
+ break;
1755
+ }
1756
+ if(PhaseSweep(ndy)) return ZBDDDG_NIL;
1757
+ return 0;
1758
+ }
1759
+
1760
+ int ZBDDDG::PrintDecomp(ZBDD f)
1761
+ {
1762
+ bddword ndx = Decomp(f);
1763
+ if(ndx == ZBDDDG_NIL) return 1;
1764
+ Print0(ndx);
1765
+ cout << "\n";
1766
+ return 0;
1767
+ }
1768
+
1769
+ void ZBDDDG::Print0(bddword ndx)
1770
+ {
1771
+ bddword lkx, lkx2;
1772
+ bddword ndx2;
1773
+ switch(_nodeA[ndx]._type)
1774
+ {
1775
+ case ZBDDDG_C0:
1776
+ cout << "0 ";
1777
+ break;
1778
+ case ZBDDDG_P1:
1779
+ cout << "OR( ";
1780
+ lkx = _nodeA[ndx]._lkx;
1781
+ ndx2 = _linkA[lkx]._ndx;
1782
+ if(_nodeA[ndx2]._type != ZBDDDG_OR)
1783
+ Print0(ndx2);
1784
+ else
1785
+ {
1786
+ lkx2 = _nodeA[ndx2]._lkx;
1787
+ while(lkx2 != ZBDDDG_NIL)
1788
+ {
1789
+ Print0(_linkA[lkx2]._ndx);
1790
+ lkx2 = _linkA[lkx2]._nxt;
1791
+ }
1792
+ }
1793
+ cout << "1 ) ";
1794
+ break;
1795
+ case ZBDDDG_LIT:
1796
+ cout << "x" << _nodeA[ndx]._f.Top() << " ";
1797
+ break;
1798
+ case ZBDDDG_AND:
1799
+ cout << "AND( ";
1800
+ lkx = _nodeA[ndx]._lkx;
1801
+ while(lkx != ZBDDDG_NIL)
1802
+ {
1803
+ Print0(_linkA[lkx]._ndx);
1804
+ lkx = _linkA[lkx]._nxt;
1805
+ }
1806
+ cout << ") ";
1807
+ break;
1808
+ case ZBDDDG_OR:
1809
+ cout << "OR( ";
1810
+ lkx = _nodeA[ndx]._lkx;
1811
+ while(lkx != ZBDDDG_NIL)
1812
+ {
1813
+ Print0(_linkA[lkx]._ndx);
1814
+ lkx = _linkA[lkx]._nxt;
1815
+ }
1816
+ cout << ") ";
1817
+ break;
1818
+ case ZBDDDG_OTHER:
1819
+ cout << "[ ";
1820
+ lkx = _nodeA[ndx]._lkx;
1821
+ while(lkx != ZBDDDG_NIL)
1822
+ {
1823
+ Print0(_linkA[lkx]._ndx);
1824
+ lkx = _linkA[lkx]._nxt;
1825
+ }
1826
+ cout << "] ";
1827
+ break;
1828
+ default:
1829
+ cerr << "<ERROR> ZBDDDG::Print0: wrong case (";
1830
+ cerr << (int)_nodeA[ndx]._type << ")\n";
1831
+ exit(1);
1832
+ }
1833
+ }
1834
+