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<Appendix Label="chap:brdbattr">2<Heading>Some Tools for Database Handling</Heading>34Two aims of the tools described in this appendix are5<List>6<Item>7speeding up selection functions8such as <Ref Func="AllCharacterTableNames" BookName="ctbllib"/>9for certain data libraries of &GAP; (with not too many entries),10in the sense that users can extend the list of attributes that are11treated in a special way12</Item>13<Item>14and a programmatic extension for rendering overviews of information15about the contents of databases,16using <Ref Func="BrowseTableFromDatabaseIdEnumerator"/>.17</Item>18</List>1920<P/>2122The &GAP; objects introduced for that are23<E>database id enumerators</E> (see <Ref Subsect="subsect:dbidenum"/>) and24<E>database attributes</E> (see <Ref Subsect="subsect:dbattr"/>).2526<P/>2728Contrary to the individual interfaces to29the &GAP; manuals (see Section <Ref Sect="sec:manualdisp"/>),30the &GAP; bibliography (see Section <Ref Sect="sec:gapbibl"/>),31and the overviews of &GAP; packages, &GAP; methods, and Conway polynomials32available in &GAP; (see Section <Ref Sect="sec:datadisp"/>),33the approach that will be described here assumes a special way to access34database entries.35Thus it depends on the structure of a given database36whether the tools described here are useful,37or whether an individual interface fits better.38Perhaps the example shown in Section <Ref Sect="sect:dbidenumxpl"/>39gives an impression what is possible.404142<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->43<Section Label="sect:dbobjects">44<Heading>&GAP; Objects for Database Handling</Heading>4546<#Include Label="subsect:dbidenum">4748<#Include Label="subsect:dbattr">4950<#Include Label="subsect:db_how_to_use">5152<#Include Label="DatabaseIdEnumerator_man">5354<#Include Label="DatabaseAttributeAdd_man">5556<#Include Label="DatabaseAttributeValueDefault_man">5758<#Include Label="DatabaseIdEnumeratorUpdate_man">5960<#Include Label="DatabaseAttributeCompute_man">6162<#Include Label="DatabaseAttributeSetData_man">6364</Section>6566<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->67<Section Label="sect:dbbrowse">68<Heading>Using Database Attributes for Browse Tables</Heading>6970<#Include Label="subsect:attr_browse_comp">7172<#Include Label="BrowseTableFromDatabaseIdEnumerator_man">7374</Section>7576<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->77<Section Label="sect:dbidenumxpl">78<Heading>Example: Database Id Enumerators and Database Attributes</Heading>7980As an example for the functions introduced in this appendix,81we introduce the <E>database of small integers</E>.8283For that, we fix a positive integer <M>n</M> and consider the integers84from <M>1</M> to <M>n</M> as the entries of our database.85Using these integers as their own identifiers,86we construct the database id enumerator.8788<Example>89gap> n:= 100;;90gap> smallintenum1:= DatabaseIdEnumerator( rec(91> identifiers:= [ 1 .. n ],92> entry:= function( dbidenum, id ) return id; end,93> ) );;94</Example>9596Examples of attributes for this database are the properties whether or not97an integer is a prime or a prime power.98There are global &GAP; functions <Ref Func="IsPrimeInt" BookName="ref"/>99and <Ref Func="IsPrimePowerInt" BookName="ref"/>100for computing these properties,101so we can define these database attributes via a <C>name</C> component;102we choose <C>"values"</C> as the <C>type</C> value,103so the values (<K>true</K> or <K>false</K>) are stored104in a list of length <M>n</M> for each of the two database attributes.105106<Example>107gap> DatabaseAttributeAdd( smallintenum1, rec(108> identifier:= "primes",109> type:= "values",110> name:= "IsPrimeInt",111> ) );112gap> DatabaseAttributeAdd( smallintenum1, rec(113> identifier:= "prime powers",114> type:= "values",115> name:= "IsPrimePowerInt",116> ) );117</Example>118119Similarly, we consider the prime factors as a database attribute.120121<Example>122gap> DatabaseAttributeAdd( smallintenum1, rec(123> identifier:= "factors",124> type:= "values",125> name:= "Factors",126> ) );127</Example>128129Another example of an attribute of integers is the residue modulo <M>11</M>.130We do not want to introduce a global &GAP; function for computing the value,131so we use the <C>create</C> component in order to define the attribute;132again, the values (integers from <M>0</M> to <M>10</M>) are stored in a list133of length <M>n</M>.134135<Example>136gap> DatabaseAttributeAdd( smallintenum1, rec(137> identifier:= "residue mod 11",138> type:= "values",139> create:= function( attr, id ) return id mod 11; end,140> ) );141</Example>142143Some integers are values of <Ref Func="Factorial" BookName="ref"/>,144and we want to record this information and show it in a browse table.145For most integers, nothing is stored and shown for this attribute,146so we choose the <C>type</C> value <C>"pairs"</C>147and precompute the information for the <C>data</C> component.148(The default for the <C>dataDefault</C> component is an empty string,149which is fine; so we need not prescribe this component.)150151<Example><![CDATA[152gap> factorialdata:= function( n )153> local result, i, f;154> result:= []; i:= 1; f:= 1;;155> while f <= n do156> Add( result, [ f, i ] ); i:= i + 1; f:= f * i;157> od;158> return result;159> end;;160gap> DatabaseAttributeAdd( smallintenum1, rec(161> identifier:= "inverse factorial",162> type:= "pairs",163> data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),164> isSorted:= true,165> ) );166]]></Example>167168We use this setup for creating a browse table.169The integers are shown as the first column,170using the <C>"self"</C> attribute.171This attribute can be used as a column of row labels172(useful if we want to keep the column visible when one scrolls the table173to the right)174or as a column in the main table175(useful if we want to search for the values);176here we choose the former possibility.177178<Example>179gap> t1:= BrowseTableFromDatabaseIdEnumerator( smallintenum1,180> [ "self" ],181> [ "primes", "prime powers", "factors", "residue mod 11",182> "inverse factorial" ] );;183</Example>184185The following session shows some of the features of the browse table.186187<Example>188gap> nop:= [ 14, 14, 14, 14, 14, 14 ];; # ``do nothing''189gap> sample_session:= Concatenation(190> # categorize by the first column, expand categories, wait, reset191> nop, "scsc", nop, "X", nop, "!",192> # sort the residue column, wait, reset193> "scrrrso", nop, "!",194> # categorize by the inverse factorial column195> "rscsrdx", nop, "!",196> # and quit the application197> "qQ" );;198gap> BrowseData.SetReplay( sample_session );199gap> NCurses.BrowseGeneric( t1 );200gap> BrowseData.SetReplay( false );201gap> Unbind( t1.dynamic.replay );202</Example>203204(Note that the last statement above is necessary to run the session205more than once.)206207The result is not too bad but we can improve the table,208using the optional components of database attributes,209as follows.210211<List>212<Item>213The strings <C>"true"</C> and <C>"false"</C> shown for the Boolean valued214database attributes can be replaced by the perhaps more suggestive strings215<C>"+"</C> and <C>"-"</C>216(or perhaps an empty string instead of <C>"-"</C>).217</Item>218<Item>219The alignment of values inside their columns can be customized.220</Item>221<Item>222When the browse table is categorized by a column then the values in this223column do usually not provide suitable category rows;224we can prescribe individual category values.225</Item>226<Item>227The column labels can be customized.228</Item>229<Item>230Where the lexicographic order is not appropriate for sorting table entries,231we can prescribe an individual comparison function.232</Item>233<Item>234Sort parameters can be customized.235</Item>236<Item>237We can prescribe the width of a column, and thus distribute the attribute238values for this column to several rows when the values are too long.239</Item>240<Item>241Finally, in the call of <Ref Func="BrowseTableFromDatabaseIdEnumerator"/>,242we can add a header to the browse table.243</Item>244</List>245246We create a new database id enumerator and the corresponding browse table,247in order to be able to compare the behaviour of the two objects.248However, we assume that the variables <C>n</C> and <C>factorialdata</C>249are already available.250251<Example>252gap> smallintenum2:= DatabaseIdEnumerator( rec(253> identifiers:= [ 1 .. n ],254> entry:= function( dbidenum, id ) return id; end,255> viewLabel:= "",256> ) );;257gap> DatabaseAttributeAdd( smallintenum2, rec(258> identifier:= "primes",259> type:= "values",260> name:= "IsPrimeInt",261> viewLabel:= "prime?",262> viewValue:= value -> BrowseData.ReplacedEntry( value,263> [ true, false ], [ "+", "-" ] ),264> sortParameters:= [ "add counter on categorizing", "yes" ],265> align:= "c",266> categoryValue:= value -> BrowseData.ReplacedEntry( value,267> [ true, false ], [ "prime", "nonprime" ] ),268> ) );269gap> DatabaseAttributeAdd( smallintenum2, rec(270> identifier:= "prime powers",271> type:= "values",272> name:= "IsPrimePowerInt",273> viewLabel:= "prime power?",274> viewValue:= value -> BrowseData.ReplacedEntry( value,275> [ true, false ], [ "+", "-" ] ),276> sortParameters:= [ "add counter on categorizing", "yes" ],277> align:= "c",278> categoryValue:= value -> BrowseData.ReplacedEntry( value,279> [ true, false ], [ "prime power", "not prime power" ] ),280> ) );281gap> DatabaseAttributeAdd( smallintenum2, rec(282> identifier:= "factors",283> type:= "values",284> name:= "Factors",285> viewLabel:= "factors",286> viewValue:= value -> JoinStringsWithSeparator( List( value, String ),287> " * "),288> widthCol:= 10,289> ) );290gap> DatabaseAttributeAdd( smallintenum2, rec(291> identifier:= "residue mod 11",292> type:= "values",293> create:= function( attr, id ) return id mod 11; end,294> viewSort:= BrowseData.SortAsIntegers,295> categoryValue:= res -> Concatenation( String( res ), " mod 11" ),296> ) );297gap> DatabaseAttributeAdd( smallintenum2, rec(298> identifier:= "inverse factorial",299> type:= "pairs",300> data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),301> isSorted:= true,302> categoryValue:= function( k )303> if k = "" then304> return "(no factorial)";305> else306> return Concatenation( String( k ), "!" );307> fi;308> end,309> ) );310gap> t2:= BrowseTableFromDatabaseIdEnumerator( smallintenum2,311> [ "self" ],312> [ "primes", "prime powers", "factors", "residue mod 11",313> "inverse factorial" ],314> t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;315</Example>316317We run the same session as with the browse table for <C>smallintenum1</C>.318319<Example>320gap> BrowseData.SetReplay( sample_session );321gap> NCurses.BrowseGeneric( t2 );322gap> BrowseData.SetReplay( false );323gap> Unbind( t2.dynamic.replay );324</Example>325326Another possibility to change the look of the table is to combine327the columns for the two Boolean valued database attributes in one column,328by showing the string <C>"+"</C> for prime powers, as before,329and showing this string in boldface red if the number in question is a prime.330331We implement this idea in the following database attribute.332However, note that this can be a bad idea because text attributes333may be not supported in the user's terminal334(see Section <Ref Subsect="ssec:ncursesAttrs"/>),335or the user may have difficulties to see or to distinguish colors;336also, it must be documented which information is encoded in the table,337and the column label might be not sufficient for explaining what338the text attributes mean.339Alternatively, we could show for example combined symbols such as <C>++</C>,340<C>+-</C>, <C>--</C> for primes, prime powers, and non-prime-powers,341respectively.342343(We see that besides these issues,344the required &GAP; code is more involved345than what is needed for the examples above.)346347<Example><![CDATA[348gap> DatabaseAttributeAdd( smallintenum2, rec(349> identifier:= "primes & prime powers",350> type:= "values",351> create:= function( attr, id )352> if IsPrimeInt( id ) then353> return 2;354> elif IsPrimePowerInt( id ) then355> return 1;356> else357> return 0;358> fi;359> end,360> viewLabel:= [ NCurses.attrs.BOLD + NCurses.ColorAttr( "red", -1 ),361> "prime", NCurses.attrs.NORMAL, " power?" ],362> viewValue:= value -> BrowseData.ReplacedEntry( value,363> [ 0, 1, 2 ], [ "-", "+",364> [ NCurses.attrs.BOLD + NCurses.ColorAttr( "red", -1 ),365> true, "+",366> NCurses.ColorAttr( "red", -1 ), false ] ] ),367> sortParameters:= [ "add counter on categorizing", "yes" ],368> align:= "c",369> categoryValue:= value -> BrowseData.ReplacedEntry( value,370> [ 0, 1, 2 ],371> [ "not prime power", "prime power, not prime", "prime" ] ),372> ) );373gap> t3:= BrowseTableFromDatabaseIdEnumerator( smallintenum2,374> [ "self" ],375> [ "primes & prime powers", "residue mod 11",376> "inverse factorial" ],377> t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;378gap> sample_session2:= Concatenation(379> # categorize by the first column, expand categories, wait, reset380> nop, "scsc", nop, "X", nop, "!", "Q" );;381gap> BrowseData.SetReplay( sample_session2 );382gap> NCurses.BrowseGeneric( t3 );383gap> BrowseData.SetReplay( false );384gap> Unbind( t3.dynamic.replay );385]]></Example>386387Now we want to consider the database as extendible,388that is, we want to be able to increase <M>n</M>389after constructing the database attributes.390For that, we use <M>n</M> as the <C>version</C> value of the391database id enumerator,392and provide <C>version</C> and <C>update</C> components for393all attributes.394395<P/>396397Again, we start the construction from scratch.398399<Example><![CDATA[400gap> smallintenum3:= DatabaseIdEnumerator( rec(401> identifiers:= [ 1 .. n ],402> entry:= function( dbidenum, id ) return id; end,403> viewLabel:= "",404> version:= n,405> update:= function( dbidenum )406> dbidenum.identifiers:= [ 1 .. n ];407> dbidenum.version:= n;408> return true;409> end,410> ) );;411gap> updateByUnbindData:= function( attr )412> Unbind( attr.data );413> return true;414> end;;415gap> DatabaseAttributeAdd( smallintenum3, rec(416> identifier:= "primes",417> type:= "values",418> name:= "IsPrimeInt",419> viewLabel:= "prime?",420> viewValue:= value -> BrowseData.ReplacedEntry( value,421> [ true, false ], [ "+", "-" ] ),422> sortParameters:= [ "add counter on categorizing", "yes" ],423> align:= "c",424> categoryValue:= value -> BrowseData.ReplacedEntry( value,425> [ true, false ], [ "prime", "nonprime" ] ),426> version:= n,427> update:= updateByUnbindData,428> ) );429gap> DatabaseAttributeAdd( smallintenum3, rec(430> identifier:= "prime powers",431> type:= "values",432> name:= "IsPrimePowerInt",433> viewLabel:= "prime power?",434> viewValue:= value -> BrowseData.ReplacedEntry( value,435> [ true, false ], [ "+", "-" ] ),436> sortParameters:= [ "add counter on categorizing", "yes" ],437> align:= "c",438> categoryValue:= value -> BrowseData.ReplacedEntry( value,439> [ true, false ], [ "prime power", "not prime power" ] ),440> version:= n,441> update:= updateByUnbindData,442> ) );443gap> DatabaseAttributeAdd( smallintenum3, rec(444> identifier:= "factors",445> type:= "values",446> name:= "Factors",447> viewLabel:= "factors",448> viewValue:= value -> JoinStringsWithSeparator( List( value, String ),449> " * "),450> widthCol:= 10,451> version:= n,452> update:= updateByUnbindData,453> ) );454gap> DatabaseAttributeAdd( smallintenum3, rec(455> identifier:= "residue mod 11",456> type:= "values",457> create:= function( attr, id ) return id mod 11; end,458> viewSort:= BrowseData.SortAsIntegers,459> categoryValue:= res -> Concatenation( String( res ), " mod 11" ),460> version:= n,461> update:= updateByUnbindData,462> ) );463gap> DatabaseAttributeAdd( smallintenum3, rec(464> identifier:= "inverse factorial",465> type:= "pairs",466> data:= rec( automatic:= factorialdata( n ), nonautomatic:= [] ),467> isSorted:= true,468> categoryValue:= function( k )469> if k = "" then470> return "(no factorial)";471> else472> return Concatenation( String( k ), "!" );473> fi;474> end,475> version:= n,476> update:= function( attr )477> attr.data.automatic:= factorialdata( n );478> return true;479> end,480> ) );481]]></Example>482483Now we can change the set of database entries by assigning a new value484to the variable <C>n</C>,485and then calling <Ref Func="DatabaseIdEnumeratorUpdate"/>.486487<Example>488gap> n:= 200;;489gap> DatabaseIdEnumeratorUpdate( smallintenum3 );490true491gap> t4:= BrowseTableFromDatabaseIdEnumerator( smallintenum3,492> [ "self" ], [ "primes", "prime powers", "factors", "residue mod 11",493> "inverse factorial" ],494> t -> BrowseData.HeaderWithRowCounter( t, "Small integers", n ) );;495gap> BrowseData.SetReplay( sample_session );496gap> NCurses.BrowseGeneric( t4 );497gap> BrowseData.SetReplay( false );498gap> Unbind( t4.dynamic.replay );499</Example>500501</Section>502503<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->504<Section Label="sect:tomlibinfo">505<Heading>Example: An Overview of the &GAP; Library of Tables of Marks506</Heading>507508The example shown in this section deals with &GAP;'s Library of509Tables of Marks (the <Package>TomLib</Package> package <Cite Key="TomLib"/>).510511<#Include Label="BrowseTomLibInfo_man">512513</Section>514515</Appendix>516517518519