tclbdd

Check-in [337aa1f548]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:progress toward a man page for tclfddd
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:337aa1f548379b7db2a1ca6abc1c0165a15d45b8
User & Date: kbk 2014-07-10 03:30:00
Context
2014-08-02
20:45
Improve FDDD documentation, and make the 'profile' method return something sensible check-in: 9b2f195e16 user: kbk tags: trunk
2014-07-10
03:30
progress toward a man page for tclfddd check-in: 337aa1f548 user: kbk tags: trunk
2014-07-05
19:33
Finish draft of man page for tclbdd(n) check-in: 97123e476e user: kbk tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to doc/tclbdd.n.

1
2
3
4
5
6
7
8
..
38
39
40
41
42
43
44











45
46
47
48
49
50
51
'\" bdd.n --
'\" 
'\"     Documentation for the 'bdd' package
'\" 
'\" Copyright (c) 2014 by Kevin B. Kenny
'\" 
'\" See the file "license.terms" for information on usage and redistribution of
'\" this file, and for a DISCLAIMER OF ALL WARRANTIES.
................................................................................
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0











..
'\" END IGNORE
.TH "bdd" n 0.1 TclBDD "Tcl Binary Decision Diagram library"
.BS
.SH "NAME"
bdd \- Binary Decision Diagram (BDD) library
.SH "SYNOPSIS"
|







 







>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
..
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
'\" tclbdd.n --
'\" 
'\"     Documentation for the 'bdd' package
'\" 
'\" Copyright (c) 2014 by Kevin B. Kenny
'\" 
'\" See the file "license.terms" for information on usage and redistribution of
'\" this file, and for a DISCLAIMER OF ALL WARRANTIES.
................................................................................
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
'\" END IGNORE
.TH "bdd" n 0.1 TclBDD "Tcl Binary Decision Diagram library"
.BS
.SH "NAME"
bdd \- Binary Decision Diagram (BDD) library
.SH "SYNOPSIS"

Added doc/tclfddd.n.

































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
'\" tclfddd.n --
'\" 
'\"     Documentation for the 'tclfddd' package
'\" 
'\" Copyright (c) 2014 by Kevin B. Kenny
'\" 
'\" See the file "license.terms" for information on usage and redistribution of
'\" this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\" .so man.macros
'\" IGNORE
.if t .wh -1.3i ^B
.nr ^l \n(.lg
.ad b
'\"	# BS - start boxed text
'\"	# ^y = starting y location
'\"	# ^b = 1
.de BS
.br
.mk ^y
.nr ^b 1u
.if n .nf
.if n .ti 0
.if n \l'\\n(.lu\(ul'
.if n .fi
..
'\"	# BE - end boxed text (draw box now)
.de BE
.nf
.ti 0
.mk ^t
.ie n \l'\\n(^lu\(ul'
.el \{\
'\"	Draw four-sided box normally, but don't draw top of
'\"	box if the box started on an earlier page.
.ie !\\n(^b-1 \{\
\h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.el \}\
\h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul'
.\}
.\}
.fi
.br
.nr ^b 0
..
.\"	# CS - begin code excerpt
.de CS
.RS
.nf
.ta .25i .5i .75i 1i
..
.\"	# CE - end code excerpt
.de CE
.fi
.RE
..
'\" END IGNORE
.TH "tclfddd" n 0.1 TclFDDD "Tcl Finitd Domainn Decision Diagram library"
.BS
.SH "NAME"
tclfddd \- Finite Domain Decision Diagram (FDDD) library
.SH "SYNOPSIS"
.nf
package require \fBtclbdd 0.1\fR
package require \fBtclfddd 0.1\fR

\fBbdd::fddd::database create\fR \fIdbname\fR \fIdomain\fR
\fBbdd::fddd::database new\fR \fIdomain\fR

\fBbdd::fddd::domain\fR \fIcolName\fR \fIwidth\fR \fIendian\fR
\fBbdd::fddd::interleave\fR ?\fIdomain\fR...?
\fBbdd::fddd::concatenate\fR ?\fIdomain\fR...?

\fIdb\fR \fBrelation\fR \fIrelation\fR ?\fIcolName\fR...?
\fIdb\fR \fBforget_relation\fR ?\fIrelation\fR...?

\fIdb\fR \fBloader\fR \fIrelation\fR

\fIdb\fR \fB===\fR \fIrelation1\fR \fIrelation2\fR
\fIdb\fR \fBantijoin\fR \fIresultRelation\fR \fIrelation1\fR \fRrelation2\fR
\fIdb\fR \fBequate\fR \fIresultRelation\fR \fIcolName1\fR \fIcolName2\fR
\fIdb\fR \fBinequality\fR \fIresultRelation\fR \fIcolName1\fR \fIcolName2\fR
\fIdb\fR \fBjoin\fR \fIresultRelation\fR \fIrelation1\fR \fRrelation2\fR
\fIdb\fR \fBnegate\fR \fIresultRelation\fR \fIrelation1\fR
\fIdb\fR \fBproject\fR \fIresultRelation\fR \fIrelation1\fR
\fIdb\fR \fBreplace\fR \fIresultRelation\fR \fIrelation1\fR ?\fIoutColName inColName\fR?...
\fIdb\fR \fBset\fR \fIresultRelation\fR \fIrelation1\fR
\fIdb\fR \fBunion\fR \fIresultRelation\fR \fIrelation1\fR

\fIdb\fR \fBcolumns\fR ?\fIrelation\fR?
\fIdb\fR \fBenumerate\fR \fIdictVar\fR \fIrelation\fR \fIscript\fR
\fIdb\fR \fBgc\fR
\fIdb\fR \fBprofile\fR \fIrelation\fR

.fi
.SH "ARGUMENTS"
.TP
\fIdbname\fR
Name to give a Finite Domain Decision Diagram (FDDD) database.
.TP
\fIdomain\fR
A description of the domain over which a database is to operate. 
A domain is created as the return value from \fBbdd::fddd::domain\fR,
\fBbdd::fddd::interleave\fR, or \fIbdd::fddd::concatenate\fR.
.TP
\fIcolName1\fR, \fIcolName2/fR, ...
Name of a column in the database
.TP
\fIwidth\fR
Width of a column's value in bits (1-64).
.TP
\fIendian\fR
Endianness of a column when assigning Boolean variables. The default is
\fBlittleendian\fR, which says that the least significant bit of a value should
get the lowest Boolean variable number. An alternative is \fBbigendian\fR,
in which the most significant bit gets the lowest variable number.
.TP
\fIrelation1\fR, \fIrelation2\fR, ...
Name of a relation in the database.
.TP
\fIdictVar\fR
Name of a variable that will receive a dictionary of values representing
one row of a relation.
.TP
\fIscript\fR
Tcl script to execute for each row of a relation.
.BE
.SH "DESCRIPTION"
The \fBtclfddd\fR package implements a relational database that is
suited to keeping large, in-memory collections of facts suitable for
logic programming. It is capable of handling relations that contain
exponentially growing numbers of tuples, provided that all the values
in the columns of the database are small integers, and the patterns that
the tuples follow are sufficiently regular that a Finite Domain Decision
Diagram (FDDD) can represent each table compactly.
.PP
FDDD's are, in turn, implemented atop Binary Decision Diagrams. Each
small-integer value in an FDDD turns into a cluster of variables in the
underlying BDD, one bit per variable. 
.SH "DESCRIBING THE DATABASE"
A database is created by constructing a \fBbdd::fddd::database\fR object,
.TP
\fBbdd::fddd::database create\fR \fIdbname\fR \fIdomain\fR
.TP
\fBbdd::fddd::database new\fR \fIdomain\fR
The constructor accepts a \fIdomain\fR, which describes all the columns
in the database and the bit positions they correspond to. Domains are
constructed by composing the commands \fBdomain\fR, \fBinterleave\fR
and \fBconcatenate\fR.
.TP
\fBbdd::fddd::domain\fR \fIcolName\fR \fIwidth\fR \fIendian\fR
The \fBdomain\fR command accepts a column name, the width in bits of the
values that the column can accommodate, and optionally a parameter that
indicates whether the column values are presented with the most significant
(\fBbigendian\fR) or least significant (\fBlittleendian\fR) bit first.
The result of the \fBdomain\fR command is a description of the given column 
suitable for passing to one of the composition commands \fBinterleave\fR
and \fBconcatenate\fR, or to the \fBfddd\fR constructor.
.TP
\fBbdd::fddd::interleave\fR ?\fIdomain\fR...?  
The \fBinterleave\fR
command takes as arguments any number of domains. Any column may
appear in only one of the \fIdomain\fR arguments. It constructs a new
domain with a bit order that is obtained by taking one bit at a time
from each of the domains in rotation. In general, columns that are to
be joined frequently should have their bits interleaved, because comparing
interleaved values takes space and time proportional to their length,
while comparing non-interleaved values takes exponential space and time.
.IP
The return value of this command is a description of the new domain.
.TP
\fBbdd::fddd::concatenate\fR ?\fIdomain\fR...?
The \fBconcatenate\fR command takes as arguments any number of domains.
Any column may appear in only one of the \fIdomain\fR arguments. The
new domain is constructed by taking the bits of the given domains in order,
without interleaving them. This ordering is appropriate for columns that
are infrequently joined, because it keeps them from interfering with comparisons
on frequently-joined ones.
.IP
The return value of this command is a description of the new domain.
.PP
\fIExample:\fR The following burst of code will create a database that has
three columns, 'person1', 'person2' and 'person3', all of which are
frequently joined. Each column can accept 8-bit values.
.CS
namespace path bdd::fddd
database create db \\
    [interleave \\
        [domain person1 8] \\
        [domain person2 8] \\
	[domain person3 8]
.CE
.PP
Once the database is created, it's next necessary to define relations.
.TP
\fIdb\fR \fBrelation\fR \fIrelation\fR ?\fIcolName\fR...?
This command defines a relation in the database \fIdb\fR. 
The relation's name is given by the \fIrelation\fR 
argument. The domain of the relation is the set of columns identified by
the \fIcolName\fR arguments. All of the columns must be in the set that
was given to the \fBfddd\fR constructor when the database was constructed.
.IP
Relations are initially empty. Tuples may be added to a relation by the
\fBload\fR method on the database (see below).
.TP
\fIdb\fR \fBforget_relation\fR ?\fIrelation\fR...?
This method removes the relations whose names are given by the \fIrelation\fR
arguments from the database \fIdb\fR. All content of the relations, and all
information about their columns, are lost.
.PP
\fIExample:\fR The following block of code defines 
relations, 'parent','temp1', 'temp2', 'temp3' and 'grandparent' 
over the columns of \fIdb\fR:
.CS
db relation parent person1 person2
db relation temp1 person1 person3
db relation temp2 person3 person2
db relation temp3 person1 person2 person3
db relation grandparent person1 person2
.CE
.SH "CODE-GENERATING METHODS"
Virtually none of the methods that operate on an FDDD database do so
directly. Instead, they generate bursts of Tcl code that carry out the
desired operations when evaluated. This is done because translating the
FDDD operations to BDD operations is relatively expensive, and the code
generation methods do it as a "compilation step", so that the actual
operation can be done repeatedly at "run time" in an inexpensive fashion.
.TP
\fIdb\fR \fBloader\fR \fIrelation\fR
This method on a database \fIdb\fR
is the fundamental way of getting values into a relation.
It accepts the name of a relation in the database, and returns
a Tcl command prefix. The calling script is expected to append
column values to the given script, in the order in which the columns
appeared in the [\fIdb\fR \fBrelation\fR] call that constructed
the relation. The values must be integers that fit in the widths of
the columns. The return value of the command that loads a tuple at
run time is the empty string.
.PP
\fIExample:\fR The following code defines a loading procedure for
the \fIparent\fR table, and defines a lookup between personal names and
numeric values. It then defines that Bob is a parent of Carol, 
Carol is a parent of Ted, and Ted is a parent of Alice.
.CS
set personList {Alice Bob Carol Ted}
set i 0
foreach p $personList { dict set personNumber $p $i; incr i }
proc assertParent {parent child} "
    variable personNumber
    [$db loader person] \\
        [dict get $personList $parent] \\
        [dict get $personList child]
"
assertParent Bob Carol
assertParent Carol Ted
assertParent Ted Alice
.CE
Many of the code-generating methods evaluate the operations of relational
algebra.
.TP
\fIdb\fR \fBantijoin\fR \fIresultRelation\fR \fIrelation1\fR \fIrelation2\fR
This method generates and returns a codeburst that computes the \fIantijoin\fR
of two tables in \fIdb\fR whose names are \fIrelation1\fR and \fIrelation2\fR.
The result, which is placed in \fIresultRelation\fR, is the set of tuples
that are present in \fIrelation1\fR but not in \fIrelation2\fR. 
.IP
If either of the input relations contains columns that are not present
in the other, the tuples of the other relation are presumed to contain
every possible value for the missing columns. Most commonly, \fIrelation2\fR
will have no excess columns, and will contain a set of values identifying
rows to be deleted.
.TP
\fIdb\fR \fBequate\fR \fIresultRelation\fR \fIcolName1\fR \fIcolName2\fR
This method generates and returns a codeburst that sets \fIresultRelation\fR
so that it contains every possible value for columns other than
\fIcolName1\fR and \fIcolName2\fR and only equal pairs of values for
those two columns. For any \fIresultRelation\fR, this set is determined 
uniquely.
.IP
The purpose of this method is to give the calling a script a way to implement
an equality constraint. Joining the result relation of \fBequate\fR to
another relation selects only those tuples of the second relation which
have equal values in the given columns.
.TP
\fIdb\fR \fBinequality\fR \fIresultRelation\fR \fIcolName1\fR \fIcolName2\fR
This method generates and returns a codeburst that sets \fIresultRelation\fR
so that it contains every possible value for columns other than
\fIcolName1\fR and \fIcolName2\fR and all but equal pairs of values for
those two columns. For any \fIresultRelation\fR, this set is determined 
uniquely.
.IP
The purpose of this method is to give the calling a script a way to implement
an inequality constraint. Joining the result relation of \fBinequality\fR to
another relation selects only those tuples of the second relation which
have different values in the given columns.
.TP
\fIdb\fR \fBjoin\fR \fIresultRelation\fR \fIrelation1\fR \fRrelation2\fR
This method generates and returns a codeburst that computes the \fIjoin\fR
of two tables in \fIdb\fR whose names are \fIrelation1\fR and \fIrelation2\fR.
The result, which is placed in \fIresultRelation\fR, is the set of tuples
that are present in both \fIrelation1\fR and \fIrelation2\fR. 
.IP
If either of the input relations contains columns that are not present
in the other, the tuples of the other relation are presumed to contain
every matching value for the missing columns. 
.TP
\fIdb\fR \fBnegate\fR \fIresultRelation\fR \fIrelation1\fR
This method generates and returns
a codeburst that will set \fIresultRelation\fR to
all possible combinations of the values of its columns that do not
appear in \fIrelation1\fR. That is, the result relation will contain a tuple
if and only if that tuple does not appear in the input relation.
.TP
\fIdb\fR \fBproject\fR \fIresultRelation\fR \fIrelation1\fR
This method generates and returns a codeburst that
takes the tuples that appear in \fIrelation1\fR, and removes
from them any columns that do not appear in the \fIresultRelation\fR.
It then sets \fIresultRelation\fR to that set of tuples. 
.IP
It is common to use projection immediately after joining two tables,
to remove the column that was used for the join.
.TP
\fIdb\fR \fBreplace\fR \fIresultRelation\fR \fIrelation1\fR ?\fIoutColName inColName\fR?...
This method generates and returns a codeburst that
takes an input relation \fIrelation1\fR in the database \fIdb\fR,
and for each tuple, constructs a tuple where the first column \fIoutColName\fR
will take the value of the first input column \fIinColName\fR, 
the second column \fIoutColName\fR
will take the value of the second input column \fIinColName\fR, and
so on. This operation is necessary to perform a \fIself-join\fR, where a
table is joined to itself by linking the values of two different columns.
.IP
See the 'grandfather' table in the example below for how to use renaming to
perform a self-join.
.IP
Replacements are done in parallel: a statement like
.IP
.CS
db replace rel2 rel1 col1 col2 col2 col1
.CE
.IP
is legal, and interchanges the values of 'col1' and 'col2'
.TP
\fIdb\fR \fBset\fR \fIresultRelation\fR \fIrelation1\fR
This method generates and returns a codeburst 
that replaces in the database \fIdb\fR the tuples
of \fIresultRelation\fR with those of \fIrelation1\fR, making
\fIresultRelation\fR a copy of \fIrelation1\fR.
.TP
\fIdb\fR \fBunion\fR \fIresultRelation\fR \fIrelation1\fR \fIrelation2\fR
This method generates and returns a codeburst that will take the union
of the set of tuples of \fIrelation1\fR in database \fIdb\fR
and the set of tuples of \fIrelation2\fR in the same database.
The result is placed in \fIresultRelation\fR.
.PP
\fIExample:\fR The following block of code constructs a \fIgrandparent\fR
relation, whose members are the set of combinations A and C for which there is
some B such that A is the parent of B and B is the parent of C.
.CS
proc findGrandparents {} "
    [db rename temp1 parent person2 person3]; 
                  # person1 is a parent of person3
    [db rename temp2 parent person1 person3];
                  # person3 is a parent of person2
    [db join temp3 temp1 temp2]; 
                  # person1 is a parent of person3, who is
                  # a parent of person2
    [db project grandparent temp3];
                  # get rid of the 'person3' column
                  # and store the 'grandparent' relation
"
findGrandparents
.CE
.\" enumerate
.\" columns, gc, profile
.SH "SEE ALSO"
.SH "KEYWORDS"
.SH "REFERENCES"
.SH "COPYRIGHT"
Copyright (c) 2014 by Kevin B. Kenny.
'\" Local Variables:
'\" mode: nroff
'\" End:
'\"

Changes to library/tclfddd.tcl.

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
...
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
	    return -code error -errorcode [list FDDD BadEndian $endian] \
		"unknown endian \"$endian\": must be bigendian or littleendian"
	}
    }
    return [list [Invert $l] $l]
}

# bdd::bdd::fddd::interleave --
#
#	Interleaves some number of finite domains so that their bit positions
#	in a BDD alternate.
#
# Usage:
#	bdd::fddd::interleave ?description...?
#
................................................................................
	    append code \; [list [namespace which sys] == :t :a :b]
	    append code \; [list [namespace which sys] & $dest $dest :t]
	}
	append code \; [list [namespace which sys] unset :a :b :t]
	return $code
    }

    # Method: forget
    #
    #	Removes relations from the database
    #
    # Usage:
    #	db forget ?relation...?
    #
    # Parameters:
    #	relation... - Names of relations to remove
    #
    # Results:
    #	None.
    #
................................................................................
    # Method: negate
    #
    #	Generates code to compute the complement of a relation. All
    #	tuples over the relation's domain will be in the output relation
    #	if they are not in the input
    #
    # Usage:
    #	$db union $dest $source
    #
    # Parameters:
    #	dest    - Name of the relation that will receive the complement
    #   source1 - Name of the input relation
    #
    # Results:
    #	Returns a burst of code that computes the complement of the







|







 







|




|







 







|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
...
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
	    return -code error -errorcode [list FDDD BadEndian $endian] \
		"unknown endian \"$endian\": must be bigendian or littleendian"
	}
    }
    return [list [Invert $l] $l]
}

# bdd::fddd::interleave --
#
#	Interleaves some number of finite domains so that their bit positions
#	in a BDD alternate.
#
# Usage:
#	bdd::fddd::interleave ?description...?
#
................................................................................
	    append code \; [list [namespace which sys] == :t :a :b]
	    append code \; [list [namespace which sys] & $dest $dest :t]
	}
	append code \; [list [namespace which sys] unset :a :b :t]
	return $code
    }

    # Method: forget_relation
    #
    #	Removes relations from the database
    #
    # Usage:
    #	db forget_relation ?relation...?
    #
    # Parameters:
    #	relation... - Names of relations to remove
    #
    # Results:
    #	None.
    #
................................................................................
    # Method: negate
    #
    #	Generates code to compute the complement of a relation. All
    #	tuples over the relation's domain will be in the output relation
    #	if they are not in the input
    #
    # Usage:
    #	$db negate $source1
    #
    # Parameters:
    #	dest    - Name of the relation that will receive the complement
    #   source1 - Name of the input relation
    #
    # Results:
    #	Returns a burst of code that computes the complement of the