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

Views: 418346
1
2
<Appendix Label="chap:brdbattr">
3
<Heading>Some Tools for Database Handling</Heading>
4
5
Two aims of the tools described in this appendix are
6
<List>
7
<Item>
8
speeding up selection functions
9
such as <Ref Func="AllCharacterTableNames" BookName="ctbllib"/>
10
for certain data libraries of &GAP; (with not too many entries),
11
in the sense that users can extend the list of attributes that are
12
treated in a special way
13
</Item>
14
<Item>
15
and a programmatic extension for rendering overviews of information
16
about the contents of databases,
17
using <Ref Func="BrowseTableFromDatabaseIdEnumerator"/>.
18
</Item>
19
</List>
20
21
<P/>
22
23
The &GAP; objects introduced for that are
24
<E>database id enumerators</E> (see <Ref Subsect="subsect:dbidenum"/>) and
25
<E>database attributes</E> (see <Ref Subsect="subsect:dbattr"/>).
26
27
<P/>
28
29
Contrary to the individual interfaces to
30
the &GAP; manuals (see Section <Ref Sect="sec:manualdisp"/>),
31
the &GAP; bibliography (see Section <Ref Sect="sec:gapbibl"/>),
32
and the overviews of &GAP; packages, &GAP; methods, and Conway polynomials
33
available in &GAP; (see Section <Ref Sect="sec:datadisp"/>),
34
the approach that will be described here assumes a special way to access
35
database entries.
36
Thus it depends on the structure of a given database
37
whether the tools described here are useful,
38
or whether an individual interface fits better.
39
Perhaps the example shown in Section <Ref Sect="sect:dbidenumxpl"/>
40
gives an impression what is possible.
41
42
43
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
44
<Section Label="sect:dbobjects">
45
<Heading>&GAP; Objects for Database Handling</Heading>
46
47
<#Include Label="subsect:dbidenum">
48
49
<#Include Label="subsect:dbattr">
50
51
<#Include Label="subsect:db_how_to_use">
52
53
<#Include Label="DatabaseIdEnumerator_man">
54
55
<#Include Label="DatabaseAttributeAdd_man">
56
57
<#Include Label="DatabaseAttributeValueDefault_man">
58
59
<#Include Label="DatabaseIdEnumeratorUpdate_man">
60
61
<#Include Label="DatabaseAttributeCompute_man">
62
63
<#Include Label="DatabaseAttributeSetData_man">
64
65
</Section>
66
67
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
68
<Section Label="sect:dbbrowse">
69
<Heading>Using Database Attributes for Browse Tables</Heading>
70
71
<#Include Label="subsect:attr_browse_comp">
72
73
<#Include Label="BrowseTableFromDatabaseIdEnumerator_man">
74
75
</Section>
76
77
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
78
<Section Label="sect:dbidenumxpl">
79
<Heading>Example: Database Id Enumerators and Database Attributes</Heading>
80
81
As an example for the functions introduced in this appendix,
82
we introduce the <E>database of small integers</E>.
83
84
For that, we fix a positive integer <M>n</M> and consider the integers
85
from <M>1</M> to <M>n</M> as the entries of our database.
86
Using these integers as their own identifiers,
87
we construct the database id enumerator.
88
89
<Example>
90
gap> n:= 100;;
91
gap> smallintenum1:= DatabaseIdEnumerator( rec(
92
> identifiers:= [ 1 .. n ],
93
> entry:= function( dbidenum, id ) return id; end,
94
> ) );;
95
</Example>
96
97
Examples of attributes for this database are the properties whether or not
98
an integer is a prime or a prime power.
99
There are global &GAP; functions <Ref Func="IsPrimeInt" BookName="ref"/>
100
and <Ref Func="IsPrimePowerInt" BookName="ref"/>
101
for computing these properties,
102
so we can define these database attributes via a <C>name</C> component;
103
we choose <C>"values"</C> as the <C>type</C> value,
104
so the values (<K>true</K> or <K>false</K>) are stored
105
in a list of length <M>n</M> for each of the two database attributes.
106
107
<Example>
108
gap> DatabaseAttributeAdd( smallintenum1, rec(
109
> identifier:= "primes",
110
> type:= "values",
111
> name:= "IsPrimeInt",
112
> ) );
113
gap> DatabaseAttributeAdd( smallintenum1, rec(
114
> identifier:= "prime powers",
115
> type:= "values",
116
> name:= "IsPrimePowerInt",
117
> ) );
118
</Example>
119
120
Similarly, we consider the prime factors as a database attribute.
121
122
<Example>
123
gap> DatabaseAttributeAdd( smallintenum1, rec(
124
> identifier:= "factors",
125
> type:= "values",
126
> name:= "Factors",
127
> ) );
128
</Example>
129
130
Another example of an attribute of integers is the residue modulo <M>11</M>.
131
We do not want to introduce a global &GAP; function for computing the value,
132
so we use the <C>create</C> component in order to define the attribute;
133
again, the values (integers from <M>0</M> to <M>10</M>) are stored in a list
134
of length <M>n</M>.
135
136
<Example>
137
gap> DatabaseAttributeAdd( smallintenum1, rec(
138
> identifier:= "residue mod 11",
139
> type:= "values",
140
> create:= function( attr, id ) return id mod 11; end,
141
> ) );
142
</Example>
143
144
Some integers are values of <Ref Func="Factorial" BookName="ref"/>,
145
and we want to record this information and show it in a browse table.
146
For most integers, nothing is stored and shown for this attribute,
147
so we choose the <C>type</C> value <C>"pairs"</C>
148
and precompute the information for the <C>data</C> component.
149
(The default for the <C>dataDefault</C> component is an empty string,
150
which is fine; so we need not prescribe this component.)
151
152
<Example><![CDATA[
153
gap> factorialdata:= function( n )
154
> local result, i, f;
155
> result:= []; i:= 1; f:= 1;;
156
> while f <= n do
157
> Add( result, [ f, i ] ); i:= i + 1; f:= f * i;
158
> od;
159
> return result;
160
> end;;
161
gap> DatabaseAttributeAdd( smallintenum1, rec(
162
> identifier:= "inverse factorial",
163
> type:= "pairs",
164
> data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),
165
> isSorted:= true,
166
> ) );
167
]]></Example>
168
169
We use this setup for creating a browse table.
170
The integers are shown as the first column,
171
using the <C>"self"</C> attribute.
172
This attribute can be used as a column of row labels
173
(useful if we want to keep the column visible when one scrolls the table
174
to the right)
175
or as a column in the main table
176
(useful if we want to search for the values);
177
here we choose the former possibility.
178
179
<Example>
180
gap> t1:= BrowseTableFromDatabaseIdEnumerator( smallintenum1,
181
> [ "self" ],
182
> [ "primes", "prime powers", "factors", "residue mod 11",
183
> "inverse factorial" ] );;
184
</Example>
185
186
The following session shows some of the features of the browse table.
187
188
<Example>
189
gap> nop:= [ 14, 14, 14, 14, 14, 14 ];; # ``do nothing''
190
gap> sample_session:= Concatenation(
191
> # categorize by the first column, expand categories, wait, reset
192
> nop, "scsc", nop, "X", nop, "!",
193
> # sort the residue column, wait, reset
194
> "scrrrso", nop, "!",
195
> # categorize by the inverse factorial column
196
> "rscsrdx", nop, "!",
197
> # and quit the application
198
> "qQ" );;
199
gap> BrowseData.SetReplay( sample_session );
200
gap> NCurses.BrowseGeneric( t1 );
201
gap> BrowseData.SetReplay( false );
202
gap> Unbind( t1.dynamic.replay );
203
</Example>
204
205
(Note that the last statement above is necessary to run the session
206
more than once.)
207
208
The result is not too bad but we can improve the table,
209
using the optional components of database attributes,
210
as follows.
211
212
<List>
213
<Item>
214
The strings <C>"true"</C> and <C>"false"</C> shown for the Boolean valued
215
database attributes can be replaced by the perhaps more suggestive strings
216
<C>"+"</C> and <C>"-"</C>
217
(or perhaps an empty string instead of <C>"-"</C>).
218
</Item>
219
<Item>
220
The alignment of values inside their columns can be customized.
221
</Item>
222
<Item>
223
When the browse table is categorized by a column then the values in this
224
column do usually not provide suitable category rows;
225
we can prescribe individual category values.
226
</Item>
227
<Item>
228
The column labels can be customized.
229
</Item>
230
<Item>
231
Where the lexicographic order is not appropriate for sorting table entries,
232
we can prescribe an individual comparison function.
233
</Item>
234
<Item>
235
Sort parameters can be customized.
236
</Item>
237
<Item>
238
We can prescribe the width of a column, and thus distribute the attribute
239
values for this column to several rows when the values are too long.
240
</Item>
241
<Item>
242
Finally, in the call of <Ref Func="BrowseTableFromDatabaseIdEnumerator"/>,
243
we can add a header to the browse table.
244
</Item>
245
</List>
246
247
We create a new database id enumerator and the corresponding browse table,
248
in order to be able to compare the behaviour of the two objects.
249
However, we assume that the variables <C>n</C> and <C>factorialdata</C>
250
are already available.
251
252
<Example>
253
gap> smallintenum2:= DatabaseIdEnumerator( rec(
254
> identifiers:= [ 1 .. n ],
255
> entry:= function( dbidenum, id ) return id; end,
256
> viewLabel:= "",
257
> ) );;
258
gap> DatabaseAttributeAdd( smallintenum2, rec(
259
> identifier:= "primes",
260
> type:= "values",
261
> name:= "IsPrimeInt",
262
> viewLabel:= "prime?",
263
> viewValue:= value -> BrowseData.ReplacedEntry( value,
264
> [ true, false ], [ "+", "-" ] ),
265
> sortParameters:= [ "add counter on categorizing", "yes" ],
266
> align:= "c",
267
> categoryValue:= value -> BrowseData.ReplacedEntry( value,
268
> [ true, false ], [ "prime", "nonprime" ] ),
269
> ) );
270
gap> DatabaseAttributeAdd( smallintenum2, rec(
271
> identifier:= "prime powers",
272
> type:= "values",
273
> name:= "IsPrimePowerInt",
274
> viewLabel:= "prime power?",
275
> viewValue:= value -> BrowseData.ReplacedEntry( value,
276
> [ true, false ], [ "+", "-" ] ),
277
> sortParameters:= [ "add counter on categorizing", "yes" ],
278
> align:= "c",
279
> categoryValue:= value -> BrowseData.ReplacedEntry( value,
280
> [ true, false ], [ "prime power", "not prime power" ] ),
281
> ) );
282
gap> DatabaseAttributeAdd( smallintenum2, rec(
283
> identifier:= "factors",
284
> type:= "values",
285
> name:= "Factors",
286
> viewLabel:= "factors",
287
> viewValue:= value -> JoinStringsWithSeparator( List( value, String ),
288
> " * "),
289
> widthCol:= 10,
290
> ) );
291
gap> DatabaseAttributeAdd( smallintenum2, rec(
292
> identifier:= "residue mod 11",
293
> type:= "values",
294
> create:= function( attr, id ) return id mod 11; end,
295
> viewSort:= BrowseData.SortAsIntegers,
296
> categoryValue:= res -> Concatenation( String( res ), " mod 11" ),
297
> ) );
298
gap> DatabaseAttributeAdd( smallintenum2, rec(
299
> identifier:= "inverse factorial",
300
> type:= "pairs",
301
> data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),
302
> isSorted:= true,
303
> categoryValue:= function( k )
304
> if k = "" then
305
> return "(no factorial)";
306
> else
307
> return Concatenation( String( k ), "!" );
308
> fi;
309
> end,
310
> ) );
311
gap> t2:= BrowseTableFromDatabaseIdEnumerator( smallintenum2,
312
> [ "self" ],
313
> [ "primes", "prime powers", "factors", "residue mod 11",
314
> "inverse factorial" ],
315
> t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;
316
</Example>
317
318
We run the same session as with the browse table for <C>smallintenum1</C>.
319
320
<Example>
321
gap> BrowseData.SetReplay( sample_session );
322
gap> NCurses.BrowseGeneric( t2 );
323
gap> BrowseData.SetReplay( false );
324
gap> Unbind( t2.dynamic.replay );
325
</Example>
326
327
Another possibility to change the look of the table is to combine
328
the columns for the two Boolean valued database attributes in one column,
329
by showing the string <C>"+"</C> for prime powers, as before,
330
and showing this string in boldface red if the number in question is a prime.
331
332
We implement this idea in the following database attribute.
333
However, note that this can be a bad idea because text attributes
334
may be not supported in the user's terminal
335
(see Section <Ref Subsect="ssec:ncursesAttrs"/>),
336
or the user may have difficulties to see or to distinguish colors;
337
also, it must be documented which information is encoded in the table,
338
and the column label might be not sufficient for explaining what
339
the text attributes mean.
340
Alternatively, we could show for example combined symbols such as <C>++</C>,
341
<C>+-</C>, <C>--</C> for primes, prime powers, and non-prime-powers,
342
respectively.
343
344
(We see that besides these issues,
345
the required &GAP; code is more involved
346
than what is needed for the examples above.)
347
348
<Example><![CDATA[
349
gap> DatabaseAttributeAdd( smallintenum2, rec(
350
> identifier:= "primes & prime powers",
351
> type:= "values",
352
> create:= function( attr, id )
353
> if IsPrimeInt( id ) then
354
> return 2;
355
> elif IsPrimePowerInt( id ) then
356
> return 1;
357
> else
358
> return 0;
359
> fi;
360
> end,
361
> viewLabel:= [ NCurses.attrs.BOLD + NCurses.ColorAttr( "red", -1 ),
362
> "prime", NCurses.attrs.NORMAL, " power?" ],
363
> viewValue:= value -> BrowseData.ReplacedEntry( value,
364
> [ 0, 1, 2 ], [ "-", "+",
365
> [ NCurses.attrs.BOLD + NCurses.ColorAttr( "red", -1 ),
366
> true, "+",
367
> NCurses.ColorAttr( "red", -1 ), false ] ] ),
368
> sortParameters:= [ "add counter on categorizing", "yes" ],
369
> align:= "c",
370
> categoryValue:= value -> BrowseData.ReplacedEntry( value,
371
> [ 0, 1, 2 ],
372
> [ "not prime power", "prime power, not prime", "prime" ] ),
373
> ) );
374
gap> t3:= BrowseTableFromDatabaseIdEnumerator( smallintenum2,
375
> [ "self" ],
376
> [ "primes & prime powers", "residue mod 11",
377
> "inverse factorial" ],
378
> t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;
379
gap> sample_session2:= Concatenation(
380
> # categorize by the first column, expand categories, wait, reset
381
> nop, "scsc", nop, "X", nop, "!", "Q" );;
382
gap> BrowseData.SetReplay( sample_session2 );
383
gap> NCurses.BrowseGeneric( t3 );
384
gap> BrowseData.SetReplay( false );
385
gap> Unbind( t3.dynamic.replay );
386
]]></Example>
387
388
Now we want to consider the database as extendible,
389
that is, we want to be able to increase <M>n</M>
390
after constructing the database attributes.
391
For that, we use <M>n</M> as the <C>version</C> value of the
392
database id enumerator,
393
and provide <C>version</C> and <C>update</C> components for
394
all attributes.
395
396
<P/>
397
398
Again, we start the construction from scratch.
399
400
<Example><![CDATA[
401
gap> smallintenum3:= DatabaseIdEnumerator( rec(
402
> identifiers:= [ 1 .. n ],
403
> entry:= function( dbidenum, id ) return id; end,
404
> viewLabel:= "",
405
> version:= n,
406
> update:= function( dbidenum )
407
> dbidenum.identifiers:= [ 1 .. n ];
408
> dbidenum.version:= n;
409
> return true;
410
> end,
411
> ) );;
412
gap> updateByUnbindData:= function( attr )
413
> Unbind( attr.data );
414
> return true;
415
> end;;
416
gap> DatabaseAttributeAdd( smallintenum3, rec(
417
> identifier:= "primes",
418
> type:= "values",
419
> name:= "IsPrimeInt",
420
> viewLabel:= "prime?",
421
> viewValue:= value -> BrowseData.ReplacedEntry( value,
422
> [ true, false ], [ "+", "-" ] ),
423
> sortParameters:= [ "add counter on categorizing", "yes" ],
424
> align:= "c",
425
> categoryValue:= value -> BrowseData.ReplacedEntry( value,
426
> [ true, false ], [ "prime", "nonprime" ] ),
427
> version:= n,
428
> update:= updateByUnbindData,
429
> ) );
430
gap> DatabaseAttributeAdd( smallintenum3, rec(
431
> identifier:= "prime powers",
432
> type:= "values",
433
> name:= "IsPrimePowerInt",
434
> viewLabel:= "prime power?",
435
> viewValue:= value -> BrowseData.ReplacedEntry( value,
436
> [ true, false ], [ "+", "-" ] ),
437
> sortParameters:= [ "add counter on categorizing", "yes" ],
438
> align:= "c",
439
> categoryValue:= value -> BrowseData.ReplacedEntry( value,
440
> [ true, false ], [ "prime power", "not prime power" ] ),
441
> version:= n,
442
> update:= updateByUnbindData,
443
> ) );
444
gap> DatabaseAttributeAdd( smallintenum3, rec(
445
> identifier:= "factors",
446
> type:= "values",
447
> name:= "Factors",
448
> viewLabel:= "factors",
449
> viewValue:= value -> JoinStringsWithSeparator( List( value, String ),
450
> " * "),
451
> widthCol:= 10,
452
> version:= n,
453
> update:= updateByUnbindData,
454
> ) );
455
gap> DatabaseAttributeAdd( smallintenum3, rec(
456
> identifier:= "residue mod 11",
457
> type:= "values",
458
> create:= function( attr, id ) return id mod 11; end,
459
> viewSort:= BrowseData.SortAsIntegers,
460
> categoryValue:= res -> Concatenation( String( res ), " mod 11" ),
461
> version:= n,
462
> update:= updateByUnbindData,
463
> ) );
464
gap> DatabaseAttributeAdd( smallintenum3, rec(
465
> identifier:= "inverse factorial",
466
> type:= "pairs",
467
> data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),
468
> isSorted:= true,
469
> categoryValue:= function( k )
470
> if k = "" then
471
> return "(no factorial)";
472
> else
473
> return Concatenation( String( k ), "!" );
474
> fi;
475
> end,
476
> version:= n,
477
> update:= function( attr )
478
> attr.data.automatic:= factorialdata( n );
479
> return true;
480
> end,
481
> ) );
482
]]></Example>
483
484
Now we can change the set of database entries by assigning a new value
485
to the variable <C>n</C>,
486
and then calling <Ref Func="DatabaseIdEnumeratorUpdate"/>.
487
488
<Example>
489
gap> n:= 200;;
490
gap> DatabaseIdEnumeratorUpdate( smallintenum3 );
491
true
492
gap> t4:= BrowseTableFromDatabaseIdEnumerator( smallintenum3,
493
> [ "self" ], [ "primes", "prime powers", "factors", "residue mod 11",
494
> "inverse factorial" ],
495
> t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;
496
gap> BrowseData.SetReplay( sample_session );
497
gap> NCurses.BrowseGeneric( t4 );
498
gap> BrowseData.SetReplay( false );
499
gap> Unbind( t4.dynamic.replay );
500
</Example>
501
502
</Section>
503
504
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
505
<Section Label="sect:tomlibinfo">
506
<Heading>Example: An Overview of the &GAP; Library of Tables of Marks
507
</Heading>
508
509
The example shown in this section deals with &GAP;'s Library of
510
Tables of Marks (the <Package>TomLib</Package> package <Cite Key="TomLib"/>).
511
512
<#Include Label="BrowseTomLibInfo_man">
513
514
</Section>
515
516
</Appendix>
517
518
519