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