Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
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
Project: cocalc-sagemath-dev-slelievre
Views: 4183461/**************************************************************************23al0.h4Colin Ramsay ([email protected])520 Dec 0067ADVANCED COSET ENUMERATOR, Version 3.00189Copyright 200010Centre for Discrete Mathematics and Computing,11Department of Mathematics and12Department of Computer Science & Electrical Engineering,13The University of Queensland, QLD 4072.14(http://staff.itee.uq.edu.au/havas)1516This is the header file for Level 0 of ACE; that is, the core enumerator17routines.1819**************************************************************************/2021#define ACE_VER "ACE 3.001"2223/******************************************************************24Stdio.h and stdlib.h will be included in all the source files,25since all of them include this file.26******************************************************************/2728#include <stdio.h>29#include <stdlib.h>3031/******************************************************************32At some time in the future, we may have to be careful as to the33types we use. For the moment we only typedef logical variables,34and stick with standard C types for the rest. The `default'35environment is 32-bit Unix, although there are a couple of places36where the code is 64-bit `compliant' to enable the 4G memory37barrier to be breached. (Any possible `problem' areas are38commented upon.) We also assume that we are in the C locale, and39that we're using the ACSII character set.40******************************************************************/4142typedef int Logic;43#define TRUE 144#define FALSE 04546/******************************************************************47Is it worth having this as a separate macro? Replace swapp by a48global temp?49******************************************************************/5051#define SWAP(i,j) { int swapp; swapp=i; i=j; j=swapp; }5253/******************************************************************54Macro for access to coset table. i is coset, j is generator (as55column number). colptr[j] stores the start address of the block of56memory for column j. CT(i,j), with j = 1...ncol, indicates the57action of the associated generator (or inverse) of column j on58coset i. It contains the coset number if known, otherwise 0 (in59column 1, -ve numbers indicate coincidences). Coset #1 is the60subgroup. Note the special macros for cols 1/2 to maximise speed61(and improve clarity), since these cols handle coincs & are heavily62used.6364Depending on the address/data memory model, how address arithmetic65is performed, the size of an int, the number of columns, and how66much (physical) memory is available, there will be some limit on67how many rows the table can have. The table size, in bytes, can68exceed 4G. However, since ints are (currently) used throughout,69the number of rows is at most 2147483647 (ie, 2^31-1). In70practice, arithmetic overflow problems, rounding effects, and guard71bands will limit the number of cosets to less than this. We try,72as far as possible, to postpone this point by performing some73potentially troublesome calculations using floats.74******************************************************************/7576#define CT(i,j) (*(colptr[(j)] + (i)))77#define COL1(i) (*(col1ptr + (i)))78#define COL2(i) (*(col2ptr + (i)))7980extern FILE *fop, *fip; /* All i/o goes through these */8182extern double begintime; /* clock() at start of current interval */83extern double endtime; /* clock() at end of current interval */84extern double deltatime; /* duration of current interval */85extern double totaltime; /* cumulative clock() time, current call */8687/******************************************************************88The ETINT macro is used end the current timing interval. It89updates the cumulative time for this run & the time of the current90interval (ie, since the last begintime). It must be paired with91the BTINT macro to set the start the next interval. The new92begintime is the old endtime, so our timings will _include_ the93time between the ETINT & the BTINT (this can be significant if, for94example, hole monitoring is on)!95******************************************************************/9697#define ETINT \98endtime = al0_clock(); \99deltatime = al0_diff(begintime,endtime); \100totaltime += deltatime;101102#define BTINT \103begintime = endtime;104105/******************************************************************106Variables to control the (progress-based) messaging feature. Such107messages are enabled if msgctrl is set, and are printed every108msgincr `actions'; where an action is a definition, a coincidence109(possibly) or a stacked deduction (possibly). msgnext keeps track110of how far away we are from the next message. Values of 1 for111msgctrl are ok, if you want to see everything that happens.112However, _lots_ of output can be produced for such small values.113If msghol is set, messages include hole information; this feature114is independant of the hlimit flag, and is time expensive.115******************************************************************/116117extern Logic msgctrl, msghol;118extern int msgincr, msgnext;119120/******************************************************************121If messaging is triggered & holes are required, print out the122current hole %'age as part of the progress message.123******************************************************************/124125#define MSGMID \126if (msghol) \127{ fprintf(fop, " h=%4.2f%%", al0_nholes()); } \128fprintf(fop, " l=%d c=+%4.2f;", lcount, deltatime);129130/******************************************************************131Logic control variables for current enumeration132******************************************************************/133134extern Logic mendel; /* If true, in R-style scan (& close) each135relator at each cyclic position for each136coset, instead of just from 1st position */137extern Logic rfill; /* If true, fill rows after scanning */138extern Logic pcomp; /* If true, compress coinc paths */139140/******************************************************************141The major user-settable parameters142******************************************************************/143144extern int maxrow; /* Max number of cosets permitted. May be145less than the actual physical table size allocated,146but not more. Should be at least 2! */147extern int rfactor; /* R-style `blocking factor' */148extern int cfactor; /* C-style `blocking factor' */149extern int comppc; /* As new cosets are required, they are150defined sequentially until the table is exhausted,151when compaction may be done. Comppc sets the152percentage of dead cosets in the table before153compaction is allowed. */154extern int nrinsgp; /* No. of relators `in' subgroup, for155C-style enumerations. */156extern int lahead; /* If 0, don't do lookahead. If 1 (or 3),157allow (cheap, R-style) lookahead from158current position (or over entire table). If 2 (or 4), allow159(expensive, C-style) lookahead over the entire table, a la ACE2160(or from current position). Note that, if mendel set, then cheap161is expensive! Lookahead is 1-level, ie, we don't look at162consequences of consequences or stack deductions. */163164/******************************************************************165If tlimit >= 0 then the total elapsed time is checked at the end of166each pass through the enumerator's main loop, and if it's more than167tlimit (in seconds) the run is stopped. Note that tlimit=0 does168precisely one pass through the main loop, since 0 >= 0. If there169is, e.g., a big collapse (so that the time round a loop becomes170very long), then the run may run over tlimit by a large amount.171However, we must ensure that when we exit due to too little time,172the table is left in a consistent state, so early bail-out is not173always possible. Another example is the CL phase, which can take174considerable time.175176If hlimit >= 0 then ditto for the % of unfilled holes in the coset177table. The % of holes is calculated by going thro the table, so178this can be a time-expensive option; we check on each pass thro the179loop. The impact is minimised if rfactor/cfactor blocking factors180are `large'. Note that the utility of this is under review, since181the % of holes tends to be static or to drift down.182******************************************************************/183184extern int tlimit, hlimit;185186/******************************************************************187Level 0 keeps track of the number of passes through the state-188machine's main loop in lcount. If llimit > 0, then the enumerator189will exit after (at most) llimit passes. You need to use this in190conjunction with the machine's flow chart, else the results might191surprise (annoy, frustrate) you!192******************************************************************/193194extern int llimit, lcount;195196/******************************************************************197The numbers of: current active cosets; maximum number of cosets198active at any time; total number of cosets defined.199******************************************************************/200201extern int nalive, maxcos, totcos;202203/******************************************************************204ctail (chead) is the tail (head) of the coincidence queue; we add205at tail & remove at head. During coincidence processing CT(high,2)206(aka COL2(high)) is used to link the coincidence queue together.207CT(high,1) (aka COL1(high)) contains minus the equivalent (lower208numbered) coset (the minus sign flags a `redundant' coset). The209queue is empty if chead = 0. Primary coincidence are always210processed immediately, and processing continues until _all_211secondary coincidences have been resolved. We _may_ discard212deductions in coincidence processing, but never coincidences. The213only place where coincidences could be `discarded' is in table214compaction; however, this is never called when the queue is non-215empty, ie, during coincidence processing.216******************************************************************/217218extern int chead, ctail;219220/******************************************************************221If pdefn>0, then gaps of length 1 found during relator scans in222C-style are preferentially filled (subject to the fill-factor,223discussed below). If pdefn=1, they are filled immediately, and if224pdefn=2, the deduction is also made (of course, these are also put225on the deduction stack too). If pdefn=3, then the gaps are noted226in the preferred definition list (pdq). Provided a live such gap227survives (and no coincidence occurs, which causes the pdq to be228discarded) the next coset will be defined to fill the oldest gap of229length 1.230231On certain examples, e.g., F(2,7), this can cause infinite looping232unless CT filling is guaranteed. This can be ensured by insisting233that at least some constant proportion of the coset table is always234kept filled & `tested'. This is done using ffactor. Before235defining a coset to fill a gap of length 1, the enumerator checks236whether ffactor*knh is at least nextdf and, if not, fills rows in237standard order. A good default value for ffactor (set by Level 1)238is int((5(ncol+2))/4). Warning: using a ffactor with a large239absolute value can cause infinite looping. However, in general, a240`large' positive value for ffactor works well. Note: we'd241`normally' expect that nextdf/knh ~ ncol+1 (ignoring coincidences,242which confuse things), so the default value of ffactor `encourages'243this ratio to grow a little.244245Note: tests indicate that the effects of the various pdefn/ffactor246combinations vary widely. It is not clear which values are good247general defaults or, indeed, whether any of the combinations is248_always_ `not too bad'.249******************************************************************/250251extern int pdefn;252extern float ffactor;253254/******************************************************************255The preferred definition queue (pdq) is implemented as a ring,256dropping earliest entries (see Havas, "Coset enumeration257strategies", ISSAC'91). It's size _must_ be a power of 2, so that258the NEXTPD macro can be fast (masking the ring index with 1...1 to259cycle from pdsiz-1 back to 0). The row/col arrays store the coset260number/generator values. Entries are added at botpd and removed261at toppd. The list is empty if botpd = toppd; so, in fact, the262list can store only pdsiz-1 values!263******************************************************************/264265extern int pdsiz;266#define NEXTPD(i) ((i+1) & (pdsiz-1))267268extern int *pdqcol, *pdqrow;269extern int toppd, botpd;270271/******************************************************************272The deduction list is organised as a stack. Deductions may be273discarded, and discards are flagged by disded, as they may impact274the validity of a finite index. (If deductions are not processed,275under some circumstances the result may be a multiple of the276actual index.) We only `log' discards if we try to stack them &277can't (ie, stack full) or if they're `potentially' meaningful (eg,278if we _know_ the table has collapsed, and index=1, then stacked279deductions are _not_ meaningful). The stack is empty if topded=-1,280and dedsiz is the available stack space.281282Note that if we define N.g = M, and thus M.G = N, we only stack283N/g. When we unstack, we test both N/g (picking up M) & M/G. We284ignore cosets that have become redundant, but we do nothing (too285expensive) about duplicates (either direct or inverted); these will286scan fast however, since `nothing' happens.287288We test various stack-handling options by the dedmode parameter. 0289means do nothing (except discard individually if no space), 1 means290purge redundancies off the top (on exiting _coinc()), 2 means291compact out all redundancies (on exiting _coinc()), and 3 means292throw away the entire stack if it overflows. Mode 4 is a fancy293mode; every time the stack overflows we call a function to294`process' it, on the basis that we're prepared to work _very_ hard295not to throw anything away. The particular function used is296subject to review; currently, we expand the space available for the297stack and move the old stack, compressing it as it's moved by298removing redundancies. In practice this works very well, and is299the default dedn handling method; it means that we always process300all deductions. In the presence of collapses, a judicious choice301of dedsize & the use of Mode 0 will often be faster however.302303Discussion: dedsiz is usually some `small' value, as the active304stack is normally small and shrinks back to empty rapidly. Since305the enumerator is `clever' enough to `notice' dropped/unprocessed306deductions & take appropriate action when checking a finite result,307it makes sense in some circumstances to drop excessive deductions.308In particular, if we have a lot of coincidences in al0_coinc, and309thus a big stack (esp. one that doesn't shrink quickly), it is much310faster to ignore these and tidy up at the end (since most of the311stack is redundant, duplicate or yields no info). This is somewhat312similar to the adaptive flag of ACE1/2. (An alternative option313would be to do a C-lookahead at the top of _cdefn() if ever dedns314have been discarded, but this could be very expensive.)315******************************************************************/316317extern int dedsiz;318extern int *dedrow, *dedcol;319extern int topded, dedmode;320extern Logic disded;321322/******************************************************************323Macro to save a deduction on the stack. Note the function call in324mode 4, if the stack overflows; this can be v. expensive if the325stack overflows repeatedly (ie, a big collapse). It's a question326of which is faster; trying hard _not_ to discard deductions, or327discarding them & having to run a checking phase at the end of an328enumeration. In practice, _dedn() doubles the stack space at each329call, so it's not actually called very often!330******************************************************************/331332#ifdef AL0_STAT333# define SAVED00 \334if (topded >= sdmax) \335{ sdmax = topded+1; }336#else337# define SAVED00338#endif339340#define SAVED(cos,gen) \341INCR(xsaved); \342if (topded >= dedsiz-1) \343{ \344INCR(sdoflow); \345switch(dedmode) \346{ \347case 3: \348disded = TRUE; \349topded = -1; \350break; \351case 4: \352al0_dedn(cos,gen); \353break; \354default: \355disded = TRUE; \356break; \357} \358} \359else \360{ \361dedrow[++topded] = cos; \362dedcol[topded] = gen; \363} \364SAVED00;365366/******************************************************************367We note where generators occur in bases of relators, so that368definitions can be applied at all essentially different positions369(edp) in C-style definitions or in C-style lookahead. edpbeg[g]370indexes array edp[], giving the first of the edps in all371(noninvolutory) relators for that generator. The edp array stores372pairs: the index in array relators where this generator occurs; the373length of the relator. edpend[g] indexes the last edp pair for374generator g. If there are no such positions edpbeg[g] < 0.375Generators are in terms of column numbers, so noninvolutory376generators have two sets of entries. Generators which are to be377_treated_ as involutions have only one column & one set of entries.378The edp of a relator xx (or x^2, or XX, or X^2) where x is to be379treated as an involution is _not_ stored, since it yields no380information in a C-style scan.381******************************************************************/382383extern int *edp, *edpbeg, *edpend;384385/******************************************************************386Group generators (aka coset table columns):387******************************************************************/388389extern int ncol; /* Number of columns in CT. Involutions390(usually) use only 1 column, noninvolutary391generators 2. */392extern int **colptr; /* Array of pointers to CT columns */393extern int *col1ptr, *col2ptr; /* Special pointers for cols 1 & 2 */394extern int *invcol; /* Table mapping columns to their inverse395columns, length ncol+1. */396397/******************************************************************398Group relators:399******************************************************************/400401extern int ndrel; /* Number of relators */402extern int *relind; /* relind[i] is the start position of ith403relator in array relators[] */404extern int *relexp; /* relexp[i] is exponent (ith rel'r) */405extern int *rellen; /* rellen[i] is total length (ith rel'r) */406extern int *relators; /* The relators, fully expanded and407duplicated for efficient scanning */408409/******************************************************************410Subgroup generators:411******************************************************************/412413extern int nsgpg; /* Number of subgroup generators */414extern int *subggen; /* All the subgroup generators */415extern int *subgindex; /* Start index of each generator */416extern int *subglength; /* Length of each generator */417418extern Logic sgdone; /* ?have they been applied to coset #1 */419420/******************************************************************421knr is the coset at which an R-style scanning against relators is422to commence; all previous (active) cosets trace complete cycles at423all relators. If knr == nextdf _and_ the table in hole-free, then424a valid index has been obtained. knh is the coset at which a425search for an undefined coset table entry is to begin; all previous426cosets have all entries in their row defined. If C-style427definitions are being (or will be) made, all previous cosets have428all entries in their row defined, and all consequences traced or429definitions stacked. (In fact, _all_ non-zero entries in the table430have been traced or stacked.) If knh == nextdf _and_ _all_431definitions have had their consequences processed, then a valid432index has been obtained. Note that currently knh is only changed433in C-style, since it is important that the property referred to434above is preserved. This effectively overloads the meaning of knh;435it should be replaced by separately maintained knh & knc variables.436This would make R-style & C-style symmetric; much nicer! It would437also allow us to differentiate between the definition strategy,438the scanning strategy, and the termination condition.439440nextdf is the next sequentially available coset. Normally 1 <= knr441< nextdf and 1 <= knh < nextdf; the value of knr vis-a-vis knh is442not fixed. If knr/knh hit nextdf, then we're done (modulo some443other conditions). Note that 1 <= nalive < nextdf <= maxrow+1. If444nextdf = maxrow+1 and we want to define a new coset, then we've445overflowed; we lookahead/compact/abort.446******************************************************************/447448extern int knr, knh, nextdf;449450/******************************************************************451Externally visible functions defined in enum.c. Note that it is452not strictly necessary to make _apply() visible across files, since453it's only called from within enum.c, but we do anyway, since a454smart-arse Level 0 user might like to use it.455******************************************************************/456457int al0_apply(int, int*, int*, Logic, Logic);458int al0_enum(int, int);459460/******************************************************************461Externally visible functions defined in coinc.c462******************************************************************/463464int al0_coinc(int, int, Logic);465466/******************************************************************467Externally visible functions defined in util0.c468******************************************************************/469470char *al0_date(void);471double al0_clock(void);472double al0_diff(double, double);473void al0_init(void);474Logic al0_compact(void);475Logic al0_stdct(void);476double al0_nholes(void);477void al0_upknh(void);478void al0_dedn(int, int);479void al0_dump(Logic);480void al0_rslt(int);481482/******************************************************************483During code development/testing and when experimenting with an484enumeration's parameters, it is often helpful to monitor how many485times a particular situation occurs. If the AL0_STAT (ie,486statistics) flag is defined, a statistics gathering & processing487package is compiled into the code. If the flag is not defined,488none of the macros generate any code, and so there is no overhead.489To add an item of interest, you have to add an "extern int x;"490declaration below, add an "int x;" definition in enum.c, add491"INCR(x);" statements where appropriate (or whatever other492processing statements are required), and add "x" to the _statinit()493& _statdump() functions.494******************************************************************/495496#ifdef AL0_STAT497498extern int cdcoinc, rdcoinc, apcoinc, rlcoinc, clcoinc,499xcoinc, xcols12, qcoinc;500extern int xsave12, s12dup, s12new;501extern int xcrep, crepred, crepwrk;502extern int xcomp, compwrk;503extern int xsaved, sdmax, sdoflow;504extern int xapply, apdedn, apdefn;505extern int rldedn, cldedn;506extern int xrdefn, rddedn, rddefn, rdfill;507508extern int xcdefn, cddproc, cdddedn, cddedn, cdgap, cdidefn,509cdidedn, cdpdl, cdpof, cdpdead, cdpdefn, cddefn;510511void al0_statinit(void);512#define STATINIT al0_statinit()513514void al0_statdump(void);515#define STATDUMP al0_statdump()516517#define INCR(x) x++518519#else520521#define STATINIT522#define STATDUMP523524#define INCR(x)525526#endif527528529530