CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

Path: gap4r8 / pkg / ace-5.2 / src / al0.h
Views: 418346
1
2
/**************************************************************************
3
4
al0.h
5
Colin Ramsay ([email protected])
6
20 Dec 00
7
8
ADVANCED COSET ENUMERATOR, Version 3.001
9
10
Copyright 2000
11
Centre for Discrete Mathematics and Computing,
12
Department of Mathematics and
13
Department of Computer Science & Electrical Engineering,
14
The University of Queensland, QLD 4072.
15
(http://staff.itee.uq.edu.au/havas)
16
17
This is the header file for Level 0 of ACE; that is, the core enumerator
18
routines.
19
20
**************************************************************************/
21
22
#define ACE_VER "ACE 3.001"
23
24
/******************************************************************
25
Stdio.h and stdlib.h will be included in all the source files,
26
since all of them include this file.
27
******************************************************************/
28
29
#include <stdio.h>
30
#include <stdlib.h>
31
32
/******************************************************************
33
At some time in the future, we may have to be careful as to the
34
types we use. For the moment we only typedef logical variables,
35
and stick with standard C types for the rest. The `default'
36
environment is 32-bit Unix, although there are a couple of places
37
where the code is 64-bit `compliant' to enable the 4G memory
38
barrier to be breached. (Any possible `problem' areas are
39
commented upon.) We also assume that we are in the C locale, and
40
that we're using the ACSII character set.
41
******************************************************************/
42
43
typedef int Logic;
44
#define TRUE 1
45
#define FALSE 0
46
47
/******************************************************************
48
Is it worth having this as a separate macro? Replace swapp by a
49
global temp?
50
******************************************************************/
51
52
#define SWAP(i,j) { int swapp; swapp=i; i=j; j=swapp; }
53
54
/******************************************************************
55
Macro for access to coset table. i is coset, j is generator (as
56
column number). colptr[j] stores the start address of the block of
57
memory for column j. CT(i,j), with j = 1...ncol, indicates the
58
action of the associated generator (or inverse) of column j on
59
coset i. It contains the coset number if known, otherwise 0 (in
60
column 1, -ve numbers indicate coincidences). Coset #1 is the
61
subgroup. Note the special macros for cols 1/2 to maximise speed
62
(and improve clarity), since these cols handle coincs & are heavily
63
used.
64
65
Depending on the address/data memory model, how address arithmetic
66
is performed, the size of an int, the number of columns, and how
67
much (physical) memory is available, there will be some limit on
68
how many rows the table can have. The table size, in bytes, can
69
exceed 4G. However, since ints are (currently) used throughout,
70
the number of rows is at most 2147483647 (ie, 2^31-1). In
71
practice, arithmetic overflow problems, rounding effects, and guard
72
bands will limit the number of cosets to less than this. We try,
73
as far as possible, to postpone this point by performing some
74
potentially troublesome calculations using floats.
75
******************************************************************/
76
77
#define CT(i,j) (*(colptr[(j)] + (i)))
78
#define COL1(i) (*(col1ptr + (i)))
79
#define COL2(i) (*(col2ptr + (i)))
80
81
extern FILE *fop, *fip; /* All i/o goes through these */
82
83
extern double begintime; /* clock() at start of current interval */
84
extern double endtime; /* clock() at end of current interval */
85
extern double deltatime; /* duration of current interval */
86
extern double totaltime; /* cumulative clock() time, current call */
87
88
/******************************************************************
89
The ETINT macro is used end the current timing interval. It
90
updates the cumulative time for this run & the time of the current
91
interval (ie, since the last begintime). It must be paired with
92
the BTINT macro to set the start the next interval. The new
93
begintime is the old endtime, so our timings will _include_ the
94
time between the ETINT & the BTINT (this can be significant if, for
95
example, hole monitoring is on)!
96
******************************************************************/
97
98
#define ETINT \
99
endtime = al0_clock(); \
100
deltatime = al0_diff(begintime,endtime); \
101
totaltime += deltatime;
102
103
#define BTINT \
104
begintime = endtime;
105
106
/******************************************************************
107
Variables to control the (progress-based) messaging feature. Such
108
messages are enabled if msgctrl is set, and are printed every
109
msgincr `actions'; where an action is a definition, a coincidence
110
(possibly) or a stacked deduction (possibly). msgnext keeps track
111
of how far away we are from the next message. Values of 1 for
112
msgctrl are ok, if you want to see everything that happens.
113
However, _lots_ of output can be produced for such small values.
114
If msghol is set, messages include hole information; this feature
115
is independant of the hlimit flag, and is time expensive.
116
******************************************************************/
117
118
extern Logic msgctrl, msghol;
119
extern int msgincr, msgnext;
120
121
/******************************************************************
122
If messaging is triggered & holes are required, print out the
123
current hole %'age as part of the progress message.
124
******************************************************************/
125
126
#define MSGMID \
127
if (msghol) \
128
{ fprintf(fop, " h=%4.2f%%", al0_nholes()); } \
129
fprintf(fop, " l=%d c=+%4.2f;", lcount, deltatime);
130
131
/******************************************************************
132
Logic control variables for current enumeration
133
******************************************************************/
134
135
extern Logic mendel; /* If true, in R-style scan (& close) each
136
relator at each cyclic position for each
137
coset, instead of just from 1st position */
138
extern Logic rfill; /* If true, fill rows after scanning */
139
extern Logic pcomp; /* If true, compress coinc paths */
140
141
/******************************************************************
142
The major user-settable parameters
143
******************************************************************/
144
145
extern int maxrow; /* Max number of cosets permitted. May be
146
less than the actual physical table size allocated,
147
but not more. Should be at least 2! */
148
extern int rfactor; /* R-style `blocking factor' */
149
extern int cfactor; /* C-style `blocking factor' */
150
extern int comppc; /* As new cosets are required, they are
151
defined sequentially until the table is exhausted,
152
when compaction may be done. Comppc sets the
153
percentage of dead cosets in the table before
154
compaction is allowed. */
155
extern int nrinsgp; /* No. of relators `in' subgroup, for
156
C-style enumerations. */
157
extern int lahead; /* If 0, don't do lookahead. If 1 (or 3),
158
allow (cheap, R-style) lookahead from
159
current position (or over entire table). If 2 (or 4), allow
160
(expensive, C-style) lookahead over the entire table, a la ACE2
161
(or from current position). Note that, if mendel set, then cheap
162
is expensive! Lookahead is 1-level, ie, we don't look at
163
consequences of consequences or stack deductions. */
164
165
/******************************************************************
166
If tlimit >= 0 then the total elapsed time is checked at the end of
167
each pass through the enumerator's main loop, and if it's more than
168
tlimit (in seconds) the run is stopped. Note that tlimit=0 does
169
precisely one pass through the main loop, since 0 >= 0. If there
170
is, e.g., a big collapse (so that the time round a loop becomes
171
very long), then the run may run over tlimit by a large amount.
172
However, we must ensure that when we exit due to too little time,
173
the table is left in a consistent state, so early bail-out is not
174
always possible. Another example is the CL phase, which can take
175
considerable time.
176
177
If hlimit >= 0 then ditto for the % of unfilled holes in the coset
178
table. The % of holes is calculated by going thro the table, so
179
this can be a time-expensive option; we check on each pass thro the
180
loop. The impact is minimised if rfactor/cfactor blocking factors
181
are `large'. Note that the utility of this is under review, since
182
the % of holes tends to be static or to drift down.
183
******************************************************************/
184
185
extern int tlimit, hlimit;
186
187
/******************************************************************
188
Level 0 keeps track of the number of passes through the state-
189
machine's main loop in lcount. If llimit > 0, then the enumerator
190
will exit after (at most) llimit passes. You need to use this in
191
conjunction with the machine's flow chart, else the results might
192
surprise (annoy, frustrate) you!
193
******************************************************************/
194
195
extern int llimit, lcount;
196
197
/******************************************************************
198
The numbers of: current active cosets; maximum number of cosets
199
active at any time; total number of cosets defined.
200
******************************************************************/
201
202
extern int nalive, maxcos, totcos;
203
204
/******************************************************************
205
ctail (chead) is the tail (head) of the coincidence queue; we add
206
at tail & remove at head. During coincidence processing CT(high,2)
207
(aka COL2(high)) is used to link the coincidence queue together.
208
CT(high,1) (aka COL1(high)) contains minus the equivalent (lower
209
numbered) coset (the minus sign flags a `redundant' coset). The
210
queue is empty if chead = 0. Primary coincidence are always
211
processed immediately, and processing continues until _all_
212
secondary coincidences have been resolved. We _may_ discard
213
deductions in coincidence processing, but never coincidences. The
214
only place where coincidences could be `discarded' is in table
215
compaction; however, this is never called when the queue is non-
216
empty, ie, during coincidence processing.
217
******************************************************************/
218
219
extern int chead, ctail;
220
221
/******************************************************************
222
If pdefn>0, then gaps of length 1 found during relator scans in
223
C-style are preferentially filled (subject to the fill-factor,
224
discussed below). If pdefn=1, they are filled immediately, and if
225
pdefn=2, the deduction is also made (of course, these are also put
226
on the deduction stack too). If pdefn=3, then the gaps are noted
227
in the preferred definition list (pdq). Provided a live such gap
228
survives (and no coincidence occurs, which causes the pdq to be
229
discarded) the next coset will be defined to fill the oldest gap of
230
length 1.
231
232
On certain examples, e.g., F(2,7), this can cause infinite looping
233
unless CT filling is guaranteed. This can be ensured by insisting
234
that at least some constant proportion of the coset table is always
235
kept filled & `tested'. This is done using ffactor. Before
236
defining a coset to fill a gap of length 1, the enumerator checks
237
whether ffactor*knh is at least nextdf and, if not, fills rows in
238
standard order. A good default value for ffactor (set by Level 1)
239
is int((5(ncol+2))/4). Warning: using a ffactor with a large
240
absolute value can cause infinite looping. However, in general, a
241
`large' positive value for ffactor works well. Note: we'd
242
`normally' expect that nextdf/knh ~ ncol+1 (ignoring coincidences,
243
which confuse things), so the default value of ffactor `encourages'
244
this ratio to grow a little.
245
246
Note: tests indicate that the effects of the various pdefn/ffactor
247
combinations vary widely. It is not clear which values are good
248
general defaults or, indeed, whether any of the combinations is
249
_always_ `not too bad'.
250
******************************************************************/
251
252
extern int pdefn;
253
extern float ffactor;
254
255
/******************************************************************
256
The preferred definition queue (pdq) is implemented as a ring,
257
dropping earliest entries (see Havas, "Coset enumeration
258
strategies", ISSAC'91). It's size _must_ be a power of 2, so that
259
the NEXTPD macro can be fast (masking the ring index with 1...1 to
260
cycle from pdsiz-1 back to 0). The row/col arrays store the coset
261
number/generator values. Entries are added at botpd and removed
262
at toppd. The list is empty if botpd = toppd; so, in fact, the
263
list can store only pdsiz-1 values!
264
******************************************************************/
265
266
extern int pdsiz;
267
#define NEXTPD(i) ((i+1) & (pdsiz-1))
268
269
extern int *pdqcol, *pdqrow;
270
extern int toppd, botpd;
271
272
/******************************************************************
273
The deduction list is organised as a stack. Deductions may be
274
discarded, and discards are flagged by disded, as they may impact
275
the validity of a finite index. (If deductions are not processed,
276
under some circumstances the result may be a multiple of the
277
actual index.) We only `log' discards if we try to stack them &
278
can't (ie, stack full) or if they're `potentially' meaningful (eg,
279
if we _know_ the table has collapsed, and index=1, then stacked
280
deductions are _not_ meaningful). The stack is empty if topded=-1,
281
and dedsiz is the available stack space.
282
283
Note that if we define N.g = M, and thus M.G = N, we only stack
284
N/g. When we unstack, we test both N/g (picking up M) & M/G. We
285
ignore cosets that have become redundant, but we do nothing (too
286
expensive) about duplicates (either direct or inverted); these will
287
scan fast however, since `nothing' happens.
288
289
We test various stack-handling options by the dedmode parameter. 0
290
means do nothing (except discard individually if no space), 1 means
291
purge redundancies off the top (on exiting _coinc()), 2 means
292
compact out all redundancies (on exiting _coinc()), and 3 means
293
throw away the entire stack if it overflows. Mode 4 is a fancy
294
mode; every time the stack overflows we call a function to
295
`process' it, on the basis that we're prepared to work _very_ hard
296
not to throw anything away. The particular function used is
297
subject to review; currently, we expand the space available for the
298
stack and move the old stack, compressing it as it's moved by
299
removing redundancies. In practice this works very well, and is
300
the default dedn handling method; it means that we always process
301
all deductions. In the presence of collapses, a judicious choice
302
of dedsize & the use of Mode 0 will often be faster however.
303
304
Discussion: dedsiz is usually some `small' value, as the active
305
stack is normally small and shrinks back to empty rapidly. Since
306
the enumerator is `clever' enough to `notice' dropped/unprocessed
307
deductions & take appropriate action when checking a finite result,
308
it makes sense in some circumstances to drop excessive deductions.
309
In particular, if we have a lot of coincidences in al0_coinc, and
310
thus a big stack (esp. one that doesn't shrink quickly), it is much
311
faster to ignore these and tidy up at the end (since most of the
312
stack is redundant, duplicate or yields no info). This is somewhat
313
similar to the adaptive flag of ACE1/2. (An alternative option
314
would be to do a C-lookahead at the top of _cdefn() if ever dedns
315
have been discarded, but this could be very expensive.)
316
******************************************************************/
317
318
extern int dedsiz;
319
extern int *dedrow, *dedcol;
320
extern int topded, dedmode;
321
extern Logic disded;
322
323
/******************************************************************
324
Macro to save a deduction on the stack. Note the function call in
325
mode 4, if the stack overflows; this can be v. expensive if the
326
stack overflows repeatedly (ie, a big collapse). It's a question
327
of which is faster; trying hard _not_ to discard deductions, or
328
discarding them & having to run a checking phase at the end of an
329
enumeration. In practice, _dedn() doubles the stack space at each
330
call, so it's not actually called very often!
331
******************************************************************/
332
333
#ifdef AL0_STAT
334
# define SAVED00 \
335
if (topded >= sdmax) \
336
{ sdmax = topded+1; }
337
#else
338
# define SAVED00
339
#endif
340
341
#define SAVED(cos,gen) \
342
INCR(xsaved); \
343
if (topded >= dedsiz-1) \
344
{ \
345
INCR(sdoflow); \
346
switch(dedmode) \
347
{ \
348
case 3: \
349
disded = TRUE; \
350
topded = -1; \
351
break; \
352
case 4: \
353
al0_dedn(cos,gen); \
354
break; \
355
default: \
356
disded = TRUE; \
357
break; \
358
} \
359
} \
360
else \
361
{ \
362
dedrow[++topded] = cos; \
363
dedcol[topded] = gen; \
364
} \
365
SAVED00;
366
367
/******************************************************************
368
We note where generators occur in bases of relators, so that
369
definitions can be applied at all essentially different positions
370
(edp) in C-style definitions or in C-style lookahead. edpbeg[g]
371
indexes array edp[], giving the first of the edps in all
372
(noninvolutory) relators for that generator. The edp array stores
373
pairs: the index in array relators where this generator occurs; the
374
length of the relator. edpend[g] indexes the last edp pair for
375
generator g. If there are no such positions edpbeg[g] < 0.
376
Generators are in terms of column numbers, so noninvolutory
377
generators have two sets of entries. Generators which are to be
378
_treated_ as involutions have only one column & one set of entries.
379
The edp of a relator xx (or x^2, or XX, or X^2) where x is to be
380
treated as an involution is _not_ stored, since it yields no
381
information in a C-style scan.
382
******************************************************************/
383
384
extern int *edp, *edpbeg, *edpend;
385
386
/******************************************************************
387
Group generators (aka coset table columns):
388
******************************************************************/
389
390
extern int ncol; /* Number of columns in CT. Involutions
391
(usually) use only 1 column, noninvolutary
392
generators 2. */
393
extern int **colptr; /* Array of pointers to CT columns */
394
extern int *col1ptr, *col2ptr; /* Special pointers for cols 1 & 2 */
395
extern int *invcol; /* Table mapping columns to their inverse
396
columns, length ncol+1. */
397
398
/******************************************************************
399
Group relators:
400
******************************************************************/
401
402
extern int ndrel; /* Number of relators */
403
extern int *relind; /* relind[i] is the start position of ith
404
relator in array relators[] */
405
extern int *relexp; /* relexp[i] is exponent (ith rel'r) */
406
extern int *rellen; /* rellen[i] is total length (ith rel'r) */
407
extern int *relators; /* The relators, fully expanded and
408
duplicated for efficient scanning */
409
410
/******************************************************************
411
Subgroup generators:
412
******************************************************************/
413
414
extern int nsgpg; /* Number of subgroup generators */
415
extern int *subggen; /* All the subgroup generators */
416
extern int *subgindex; /* Start index of each generator */
417
extern int *subglength; /* Length of each generator */
418
419
extern Logic sgdone; /* ?have they been applied to coset #1 */
420
421
/******************************************************************
422
knr is the coset at which an R-style scanning against relators is
423
to commence; all previous (active) cosets trace complete cycles at
424
all relators. If knr == nextdf _and_ the table in hole-free, then
425
a valid index has been obtained. knh is the coset at which a
426
search for an undefined coset table entry is to begin; all previous
427
cosets have all entries in their row defined. If C-style
428
definitions are being (or will be) made, all previous cosets have
429
all entries in their row defined, and all consequences traced or
430
definitions stacked. (In fact, _all_ non-zero entries in the table
431
have been traced or stacked.) If knh == nextdf _and_ _all_
432
definitions have had their consequences processed, then a valid
433
index has been obtained. Note that currently knh is only changed
434
in C-style, since it is important that the property referred to
435
above is preserved. This effectively overloads the meaning of knh;
436
it should be replaced by separately maintained knh & knc variables.
437
This would make R-style & C-style symmetric; much nicer! It would
438
also allow us to differentiate between the definition strategy,
439
the scanning strategy, and the termination condition.
440
441
nextdf is the next sequentially available coset. Normally 1 <= knr
442
< nextdf and 1 <= knh < nextdf; the value of knr vis-a-vis knh is
443
not fixed. If knr/knh hit nextdf, then we're done (modulo some
444
other conditions). Note that 1 <= nalive < nextdf <= maxrow+1. If
445
nextdf = maxrow+1 and we want to define a new coset, then we've
446
overflowed; we lookahead/compact/abort.
447
******************************************************************/
448
449
extern int knr, knh, nextdf;
450
451
/******************************************************************
452
Externally visible functions defined in enum.c. Note that it is
453
not strictly necessary to make _apply() visible across files, since
454
it's only called from within enum.c, but we do anyway, since a
455
smart-arse Level 0 user might like to use it.
456
******************************************************************/
457
458
int al0_apply(int, int*, int*, Logic, Logic);
459
int al0_enum(int, int);
460
461
/******************************************************************
462
Externally visible functions defined in coinc.c
463
******************************************************************/
464
465
int al0_coinc(int, int, Logic);
466
467
/******************************************************************
468
Externally visible functions defined in util0.c
469
******************************************************************/
470
471
char *al0_date(void);
472
double al0_clock(void);
473
double al0_diff(double, double);
474
void al0_init(void);
475
Logic al0_compact(void);
476
Logic al0_stdct(void);
477
double al0_nholes(void);
478
void al0_upknh(void);
479
void al0_dedn(int, int);
480
void al0_dump(Logic);
481
void al0_rslt(int);
482
483
/******************************************************************
484
During code development/testing and when experimenting with an
485
enumeration's parameters, it is often helpful to monitor how many
486
times a particular situation occurs. If the AL0_STAT (ie,
487
statistics) flag is defined, a statistics gathering & processing
488
package is compiled into the code. If the flag is not defined,
489
none of the macros generate any code, and so there is no overhead.
490
To add an item of interest, you have to add an "extern int x;"
491
declaration below, add an "int x;" definition in enum.c, add
492
"INCR(x);" statements where appropriate (or whatever other
493
processing statements are required), and add "x" to the _statinit()
494
& _statdump() functions.
495
******************************************************************/
496
497
#ifdef AL0_STAT
498
499
extern int cdcoinc, rdcoinc, apcoinc, rlcoinc, clcoinc,
500
xcoinc, xcols12, qcoinc;
501
extern int xsave12, s12dup, s12new;
502
extern int xcrep, crepred, crepwrk;
503
extern int xcomp, compwrk;
504
extern int xsaved, sdmax, sdoflow;
505
extern int xapply, apdedn, apdefn;
506
extern int rldedn, cldedn;
507
extern int xrdefn, rddedn, rddefn, rdfill;
508
509
extern int xcdefn, cddproc, cdddedn, cddedn, cdgap, cdidefn,
510
cdidedn, cdpdl, cdpof, cdpdead, cdpdefn, cddefn;
511
512
void al0_statinit(void);
513
#define STATINIT al0_statinit()
514
515
void al0_statdump(void);
516
#define STATDUMP al0_statdump()
517
518
#define INCR(x) x++
519
520
#else
521
522
#define STATINIT
523
#define STATDUMP
524
525
#define INCR(x)
526
527
#endif
528
529
530