# For AI agents Finite group database provide mathematical facts for finite groups. AI agents can use the service in one of the following ways: - Find lists of group by query - Find a group by name - Download a group's data as JSON (see JSON data) - Query the catalog with SQL, answered as JSON (see Direct SQL access) ## Database Service * Data are idempotent that never change. * Missing data get filled over time: New groups are continuously added to the database. For existing groups in the DB, new properties such as tags and relationships are also incrementally added. Check back for additions. * List of properties provided: ## URL schema * Every group has one permanent id that never changes. * JSON data: `/api/g/.json`, `/api/g/_subgroups.json`, `/api/g/_character_table.json` (see JSON data) * SQL: `/api/sql?q=` (JSON), `/sql?q=` (a list of groups), and the query schema `/schema.sql` (see Direct SQL access) ## JSON data Each group's facts are three JSON files. The file name holds the id and the content, so saved copies of many groups share one folder without clashing. | URL | Content | | --- | --- | | `/api/g/.json` | Everything the group page `/g/` states, except the subgroup list and the character table (never included, whatever the group's size) | | `/api/g/_subgroups.json` | The subgroup list: every node, the cover edges, the named subgroups, the maximal subgroup types | | `/api/g/_character_table.json` | The conjugacy classes and the character table | Each group page names its file in ``: ``. Conventions: * Every key is always present. `null` means no value is recorded (not computed, not named); it never means false, zero or empty. * `properties` lists the properties that hold. An unlisted property is false or undecided. * A group reference is `{"gid": 12, "name": "D4"}`. `name` is a search expression that finds the group: `D4`, `C2^2*C3`, `C2*S3`, `(C2*C4):C3`, or `#` for a group with no name. * Integers are exact. `aut_order`, `multiplicity`, `fan_out` and the subgroup counts can exceed 2⁵³; read them with an arbitrary-precision JSON reader. * `format` is the contract version, `1`. Added keys do not change it. * Errors: HTTP 404 or 500 with `{"error": "…"}`. * Any origin may read the files (`Access-Control-Allow-Origin: *`). The subgroup list: * `subgroups.regime`: `complete` (every subgroup), `normal_only` (the normal subgroups only; too many subgroups to list), `not_computed`. * A node is a set of `multiplicity` conjugacy classes of subgroups with one subgroup type, quotient type, class size and complementation. It is a union of `Aut(G)`-orbits of classes: one orbit for an abelian group, possibly several otherwise. * Refer to a node by `index`: `0` is `G`, the last is the trivial subgroup. Two nodes are different subgroups even when isomorphic. * An edge `{"parent", "child", "fan_out"}` says a subgroup of `child` is covered by one of `parent`; `fan_out` counts the classes of `child` adjacent to one class of `parent`. The character table: * `completeness`: `full`, `classes_only` (more than 1024 classes: no values), `count_only`, `none`. * The value of character `i` on class `j` is `palette[rows[i][j]]`. A palette entry states the value three ways: `n` and `terms` (`[[k, c], …]` for Σ c·ζₙᵏ, exact), `gap` (GAP syntax, exact), `text` (for display). * Class `j` has `size`, `element_order` and `power`, the class of xᵖ for p the smallest prime dividing the order. * The class order is not GAP's: match classes by size, element order and power map. ## Search ### List of named families ### Expression based search syntax ## Direct SQL access Run one SQL query against the catalog. Two endpoints take the same query: | Endpoint | Returns | | --- | --- | | `/api/sql` | Any columns you select, as JSON. Use this to read data. | | `/sql` | One column of group ids, as an HTML page listing those groups. | Start by reading the query schema, `/schema.sql`: every table and column a query may read, what each column means, the index each kind of query needs, and the ids of the tag, relation and subgroup-name kinds. ### `/api/sql`: any columns, as JSON Send the SQL either way: * `GET /api/sql?q=`, with the SQL URL-encoded. * `POST /api/sql` with the SQL as the request body (`Content-Type: text/plain`), for a query too long for a URL. The answer to `SELECT id, small_groups_index, nilpotency_class FROM groups WHERE group_order = 24 ORDER BY id LIMIT 3`: ```json { "format": 1, "columns": ["id", "small_groups_index", "nilpotency_class"], "rows": [[60, 1, -1], [61, 2, 1], [62, 3, -1]], "truncated": false } ``` * `columns` holds the names the query gives its result columns. Name every computed column with `AS`. * `rows` holds one array per row, in the query's order, with one value per column. `NULL` is `null`, an INTEGER or REAL is a number, and TEXT is a string. Integers are exact and can exceed 2⁵³; read them with an arbitrary-precision JSON reader. * An answer holds at most 10,000 rows and 16 MiB of rows. When `truncated` is true, more rows follow; fetch them by key, not by `OFFSET`: `... WHERE id > ORDER BY id`. * Values keep the stored conventions of `/schema.sql`: `NULL` means not known yet unless a column says otherwise, lists are text such as `'2^2,3'`, and 9223372036854775807 in an order column means at least that large. * Any origin may read it (`Access-Control-Allow-Origin: *`). Errors come back as `{"reason": "…", "error": ""}`: | Status | `reason` | Meaning | | --- | --- | --- | | 400 | `empty` | No query was sent. | | 400 | `too_long` | The SQL is longer than 64 KiB. | | 400 | `sql` | SQLite refused it: a syntax error, an unknown table or column, or not a single read-only `SELECT`. | | 400 | `unlisted` | It reads a table or column `/schema.sql` does not declare. Name the declared columns; `SELECT *` takes every column of a table, declared or not. | | 400 | `whole_table_read` | It reads a whole table. Reach the table through an index (see the rules below). | | 400 | `timeout` | It ran past 20 seconds. | | 400 | `unrepresentable` | It returns a BLOB or an infinite REAL, which JSON cannot write. | | 400 | `too_large` | Its first row alone is over 16 MiB. | | 503 | `busy` | Every query slot is in use. Retry after the `Retry-After` seconds. | | 500 | `database` | The server failed; retry later. | Examples: * Groups of order 24, with their SmallGroup index and nilpotency class: `SELECT id, small_groups_index, nilpotency_class FROM groups WHERE group_order = 24` * How many groups of each order up to 64: `SELECT group_order, count(*) AS n FROM groups WHERE group_order BETWEEN 1 AND 64 GROUP BY group_order` * Dihedral groups by name, smallest first: `SELECT g.id, g.group_order, n.group_name FROM group_names n JOIN groups g ON g.id = n.group_id WHERE n.tag_id = (SELECT tag_id FROM group_tag_kinds WHERE name = 'dihedral') ORDER BY g.group_order LIMIT 20` * The subgroup classes of group 12: `SELECT subgroup_gid, quotient_gid, class_size, multiplicity FROM subgroup_nodes WHERE gid = 12 ORDER BY subgroup_index` A group id in an answer leads to the group's full facts at `/api/g/.json`. ### `/sql`: a list of groups `GET /sql?q=`, with the SQL URL-encoded, answers with an HTML page listing the groups the query selects: a table of order and group, each group linked as `/g/`. People type queries at `/sql`. The query must return exactly one column, each value the id of a group: `groups.id`, or a column holding one, such as `group_tags.gid` or `perfect_groups.group_id`. A NULL, a text value, or an id with no group is refused. The first 100 rows are listed, in the query's order; the page says when the query returns more. A refused or stopped query answers HTTP 400 with the reason, and a busy server answers 503. Examples: * Groups of order 24: `/sql?q=SELECT%20id%20FROM%20groups%20WHERE%20group_order%20%3D%2024` * Non-abelian simple groups, by order: `SELECT group_id FROM perfect_groups WHERE simpleness = 2 ORDER BY group_order, library_index` ### Rules for both A query must: * Be one read-only `SELECT` statement; a `WITH` clause is allowed. * Read only the tables and columns `/schema.sql` declares. List the columns you want. * Be indexed: reach each table through an index, by an equality or range condition on an indexed column. A query whose plan scans a whole table is refused. Only `group_tag_kinds`, `perfect_groups`, `relation_kinds` and `subgroup_name_kinds` may be read in full; name them without an alias. * Finish within 20 seconds. ## Bulk data download ## Connection to GAP