Presentation helpers

This page contains the documentation for various helper functions for manipulating presentations.

Types

In what follows, we use the following pseudo-types:

  • Letter for str | int

  • Word for str | list[int]

Recall that, once a presentation has been constructed, the type of its letters and words are fixed.

Contents

add_identity_rules(…)

Add rules for an identity element.

add_inverse_rules(…)

Add rules for inverses.

add_rule(…)

Check and add a rule to the presentation.

add_rules(…)

Add the rules of q to p.

add_zero_rules(…)

Add rules for a zero element.

are_rules_sorted(…)

Check the rules are sorted relative to shortlex.

change_alphabet(…)

Change or re-order the alphabet.

contains_rule(…)

Check if a presentation contains a rule.

first_unused_letter(…)

Return the first letter not in the alphabet of a presentation.

greedy_reduce_length(…)

Greedily reduce the length of the presentation using longest_subword_reducing_length.

greedy_reduce_length_and_number_of_gens(…)

Greedily reduce the length and number of generators of the presentation.

is_strongly_compressible(…)

Return true if the \(1\)-relation presentation can be strongly compressed.

length(…)

Return the sum of the lengths of the rules.

longest_rule(…)

Return the index of the left-hand side of the longest rule.

longest_rule_length(…)

Return the maximum length of a rule in the presentation.

longest_subword_reducing_length(…)

Return the longest common subword of the rules.

make_semigroup(…)

Convert a monoid presentation to a semigroup presentation.

normalize_alphabet(…)

Normalize the alphabet to \(\{0, \ldots, n - 1\}\).

reduce_complements(…)

If there are rules \(u = v\) and \(v = w\) where \(|w| < |v|\), then replace \(u = v\) by \(u = w\).

reduce_to_2_generators(…)

Reduce the number of generators in a one relation presentation to 2.

remove_duplicate_rules(…)

Remove duplicate rules.

remove_redundant_generators(…)

Remove any trivially redundant generators.

remove_trivial_rules(…)

Remove rules consisting of identical words.

replace_subword(…)

Replace non-overlapping instances of a subword by another word.

replace_word(…)

Replace instances of a word on either side of a rule by another word.

replace_word_with_new_generator(…)

Replace non-overlapping instances of a word with a new generator.

reverse(…)

Reverse every rule.

shortest_rule(…)

Return the index of the left-hand side of the shortest rule.

shortest_rule_length(…)

Return the minimum length of a rule in the presentation.

sort_each_rule(…)

Overloaded function.

sort_rules(…)

Sort all of the rules by shortlex.

strongly_compress(…)

Strongly compress a one relation presentation.

throw_if_bad_inverses(…)

Validate if vals act as semigroup inverses in p.

to_gap_string(…)

Return the code that would create p in GAP.

Full API

The full API for Presentation helper functions is given below.

presentation.add_identity_rules(p: Presentation, e: Letter) None

Add rules for an identity element.

Adds rules of the form \(ae = ea = a\) for every letter \(a\) in the alphabet of p, and where \(e\) is the second parameter.

Parameters:
  • p (Presentation) – the presentation to add rules to.

  • e (Letter) – the identity element.

Raises:

LibsemigroupsError – if e is not a letter in p.alphabet().

Complexity:

Linear in the number of rules.

presentation.add_inverse_rules(p: Presentation, vals: Word, e: Letter = UNDEFINED) None

Add rules for inverses.

The letter a with index i in vals is the inverse of the letter in alphabet() with index i. The rules added are \(a_ib_i = e\) where the alphabet is \(\{a_1, \ldots, a_n\}\) ; the 2nd parameter vals is \(\{b_1, \ldots, b_n\}\) ; and \(e\) is the 3rd parameter.

Parameters:
  • p (Presentation) – the presentation to add rules to.

  • vals (Word) – the inverses.

  • e (Letter) – the identity element (defaults to UNDEFINED, meaning use the empty word).

Raises:
Complexity:

\(O(n)\) where \(n\) is p.alphabet().size().

presentation.add_rule(p: Presentation, lhop: Word, rhop: Word) None

Check and add a rule to the presentation.

Adds the rule with left-hand side lhop and right-hand side rhop to the rules, after checking that lhop and rhop consist entirely of letters in the alphabet of p.

Parameters:
  • p (Presentation) – the presentation.

  • lhop (Word) – the left-hand side of the rule.

  • rhop (Word) – the right-hand side of the rule.

Raises:

LibsemigroupsError – if lhop or rhop contains any letters not belonging to p.alphabet().

presentation.add_rules(p: Presentation, q: Presentation) None

Add the rules of q to p.

Before it is added, each rule is validated to check it contains only letters of the alphabet of p. If the \(n`th rule causes this function to throw, the first :math:`n-1\) rules will still be added to p.

Parameters:
Raises:

LibsemigroupsError – if any rule contains any letters not belonging to p.alphabet().

presentation.add_zero_rules(p: Presentation, z: Letter) None

Add rules for a zero element.

Adds rules of the form \(az = za = z\) for every letter \(a\) in the alphabet of p, and where \(z\) is the second parameter.

Parameters:
Raises:

LibsemigroupsError – if z is not a letter in p.alphabet().

Complexity:

Linear in the number of rules.

presentation.are_rules_sorted(p: Presentation) bool

Check the rules are sorted relative to shortlex.

Check if the rules \(u_1 = v_1, \ldots, u_n = v_n\) satisfy \(u_1v_1 < \cdots < u_nv_n\) where \(<\) is shortlex order.

Parameters:

p (Presentation) – the presentation to check.

Returns:

whether the rules are sorted.

Return type:

bool

Raises:

LibsemigroupsError – if p.rules.size() is odd.

See also

presentation.change_alphabet(p: Presentation, new_alphabet: Word) None

Change or re-order the alphabet.

This function replaces p.alphabet() with new_alphabet, where possible, and re-writes the rules in the presentation using the new alphabet.

Parameters:
  • p (Presentation) – the presentation.

  • new_alphabet (Word) – the replacement alphabet.

Raises:

LibsemigroupsError – if the size of p.alphabet() and new_alphabet do not agree.

presentation.contains_rule(p: Presentation, lhs: Word, rhs: Word) bool

Check if a presentation contains a rule.

Checks if the rule with left-hand side lhs and right-hand side rhs is contained in p.

Parameters:
  • p (Presentation) – the presentation.

  • lhs (Word) – the left-hand side of the rule.

  • rhs (Word) – the right-hand side of the rule.

Returns:

whether the presentation contains the rule

Return type:

bool

Complexity:

Linear in the number of rules.

presentation.first_unused_letter(p: Presentation) Letter

Return the first letter not in the alphabet of a presentation.

This function returns letter(p, i) when i is the least possible value such that !p.in_alphabet(letter(p, i)) if such a letter exists.

Parameters:

p (Presentation) – the presentation.

Returns:

the letter.

Return type:

Letter

Raises:

LibsemigroupsError – if p already has an alphabet of the maximum possible size.

presentation.greedy_reduce_length(p: Presentation) None

Greedily reduce the length of the presentation using longest_subword_reducing_length.

This function repeatedly calls longest_subword_reducing_length and replace_subword to introduce a new generator and reduce the length of the presentation p until longest_subword_reducing_length returns the empty word.

Parameters:

p (Presentation) – the presentation.

Raises:

LibsemigroupsError – if longest_subword_reducing_length or replace_word does.

presentation.greedy_reduce_length_and_number_of_gens(p: Presentation) None

Greedily reduce the length and number of generators of the presentation.

This function repeatedly calls longest_subword_reducing_length and replace_subword to introduce a new generator to try to reduce the length of the presentation p and the number of generators. This is done until either longest_subword_reducing_length returns the empty word, or the new length and number of generators is greater than or equal to that of the presentation in the previous iteration.

In the latter case, the presentation p gets restored to the state it was in after the previous iteration.

Parameters:

p (Presentation) – the presentation.

Raises:

LibsemigroupsError – if longest_subword_reducing_length or replace_word does.

presentation.is_strongly_compressible(p: Presentation) bool

Return true if the \(1\)-relation presentation can be strongly compressed.

A \(1\) -relation presentation is strongly compressible if both relation words start with the same letter and end with the same letter. In other words, if the alphabet of the presentation p is \(A\) and the relation words are of the form \(aub = avb\) where \(a, b\in A\) (possibly :math:` a = b` ) and \(u, v\in A ^ *\), then p is strongly compressible. See`Section 3.2 <https://doi.org/10.1007/s00233-021-10216-8>`_ for details.

Parameters:

p (Presentation) – the presentation.

Returns:

whether the presentation is strongly compressible

Return type:

bool

presentation.length(p: Presentation) int

Return the sum of the lengths of the rules.

Parameters:

p (Presentation) – the presentation.

Returns:

the length of the presentation

Return type:

int

presentation.longest_rule(p: Presentation) int

Return the index of the left-hand side of the longest rule.

Returns the index of the left-hand side of the first rule in the presentation with maximal length. The length of a rule is defined to be the sum of the lengths of its left-hand and right-hand sides.

Parameters:

p (Presentation) – the presentation.

Returns:

the index of the rule

Return type:

int

Raises:

LibsemigroupsError – if the length of p.rules is odd.

presentation.longest_rule_length(p: Presentation) int

Return the maximum length of a rule in the presentation.

Returns the maximum length of a rule in the presentation. The length of a rule is defined to be the sum of the lengths of its left-hand and right-hand sides.

Parameters:

p (Presentation) – the presentation.

Returns:

the maximum length

Return type:

int

Raises:

LibsemigroupsError – if the length of p.rules is odd.

presentation.longest_subword_reducing_length(p: Presentation) Word

Return the longest common subword of the rules.

If it is possible to find a subword \(w\) of the rules \(u_1 = v_1, \ldots, u_n = v_n\) such that the introduction of a new generator \(z\) and the relation \(z = w\) reduces the presentation.length of the presentation, then this function returns the longest such word \(w\). If no such word can be found, then a word of length \(0\) is returned.

Parameters:

p (Presentation) – the presentation.

Returns:

the longest common subword, if it exists.

Return type:

Word

presentation.make_semigroup(p: Presentation) Letter | Undefined

Convert a monoid presentation to a semigroup presentation.

This function modifies its argument in-place by replacing the empty word in all relations by a new generator, and the identity rules for that new generator. If p.contains_empty_word() is False, then the presentation is not modified and UNDEFINED is returned. If a new generator is added as the identity, then this generator is returned.

Parameters:

p (Presentation) – the presentation.

Returns:

The new generator added, if any, and UNDEFINED if not.

Return type:

Letter | Undefined

Raises:

LibsemigroupsError – if replace_word or add_identity_rules does.

presentation.normalize_alphabet(p: Presentation) None

Normalize the alphabet to \(\{0, \ldots, n - 1\}\).

Modify the presentation in-place so that the alphabet is \(\{0, \ldots, n - 1\}\) (or equivalent) and rewrites the rules to use this alphabet. If the alphabet is already normalized, then no changes are made to the presentation.

Parameters:

p (Presentation) – the presentation.

Raises:

LibsemigroupsError – if Presentation.throw_if_bad_alphabet_or_rules throws on the initial presentation.

presentation.reduce_complements(p: Presentation) None

If there are rules \(u = v\) and \(v = w\) where \(|w| < |v|\), then replace \(u = v\) by \(u = w\).

Attempts to reduce the length of the words by finding the equivalence relation on the relation words generated by the pairs of identical relation words. If \(\{u_1, u_2, \ldots, u_n\}\) are the distinct words in an equivalence class and \(u_1\) is the short-lex minimum word in the class, then the relation words are replaced by \(u_1 = u_2, u_1 = u_3, \cdots, u_1 = u_n\). The rules may be reordered by this function even if there are no reductions found.

Parameters:

p (Presentation) – the presentation to add rules to.

Raises:

LibsemigroupsError – if p.rules.size() is odd.

presentation.reduce_to_2_generators(p: Presentation, index: int) bool

Reduce the number of generators in a one relation presentation to 2.

Reduce the number of generators in a one relation presentation to 2. Returns True if the one relation presentation p has been modified and False if not. A one relation presentation is left cycle-free if the relation words start with distinct letters. In other words, if the alphabet of the presentation p is \(A\) and the relation words are of the form \(au = bv\) where \(a, b\in A\) with \(a \neq b\) and \(u, v \in A ^ *\), then p is left cycle-free.

The word problem for a left cycle-free one relation monoid is solvable if the word problem for the modified version obtained from this function is solvable.

Parameters:
  • p (Presentation) – the presentation.

  • index (int) – determines the choice of letter to use, 0 uses p.rules[0][0] and 1 uses p.rules[1][0] (defaults to: 0).

Returns:

Whether or not the presentation has been modified.

Return type:

bool

Raises:

LibsemigroupsError – if index is not 0 or 1.

presentation.remove_duplicate_rules(p: Presentation) None

Remove duplicate rules.

Removes all but one instance of any duplicate rules (if any). Note that rules of the form \(u = v\) and \(v = u\) (if any) are considered duplicates. Also note that the rules may be reordered by this function even if there are no duplicate rules.

Parameters:

p (Presentation) – the presentation.

Raises:

LibsemigroupsError – if p.rules.size() is odd.

Complexity:

Linear in the number of rules.

presentation.remove_redundant_generators(p: Presentation) None

Remove any trivially redundant generators.

If one side of any of the rules in the presentation p is a letter a and the other side of the rule does not contain a, then this function replaces every occurrence of a in every rule by the other side of the rule. This substitution is performed for every such rule in the presentation; and the trivial rules (with both sides being identical) are removed. If both sides of a rule are letters, then the greater letter is replaced by the lesser one.

Parameters:

p (Presentation) – the presentation.

Raises:

LibsemigroupsError – if p.rules.size() is odd.

presentation.remove_trivial_rules(p: Presentation) None

Remove rules consisting of identical words.

Removes all instance of rules (if any) where the left-hand side and the right-hand side are identical.

Parameters:

p (Presentation) – the presentation.

Raises:

LibsemigroupsError – if p.rules.size() is odd.

Complexity:

Linear in the number of rules.

presentation.replace_subword(p: Presentation, existing: Word, replacement: Word) None

Replace non-overlapping instances of a subword by another word.

If existing and replacement are words, then this function replaces every non-overlapping instance of existing in every rule by replacement. The presentation p is changed in-place.

Parameters:
  • p (Presentation) – the presentation.

  • existing (Word) – the word to be replaced.

  • replacement (Word) – the replacement word.

Raises:

LibsemigroupsError – if existing is empty.

presentation.replace_word(p: Presentation, existing: Word, replacement: Word) None

Replace instances of a word on either side of a rule by another word.

If existing and replacement are words, then this function replaces every instance of existing in every rule of the form existing \(= w\) or \(w =\) existing, with the word replacement. The presentation p is changed in-place.

Parameters:
  • p (Presentation) – the presentation.

  • existing (Word) – the word to be replaced.

  • replacement (Word) – the replacement word.

presentation.replace_word_with_new_generator(p: Presentation, w: Word) Letter

Replace non-overlapping instances of a word with a new generator.

This function replaces every non-overlapping instance (from left to right) of w in every rule, adds a new generator \(z\), and the rule \(w = z\). The new generator and rule are added even if w is not a subword of any rule.

Parameters:
Returns:

The new generator added.

Return type:

Letter

Raises:

LibsemigroupsError – if w is empty.

presentation.reverse(p: Presentation) None

Reverse every rule.

Parameters:

p (Presentation) – the presentation.

presentation.shortest_rule(p: Presentation) int

Return the index of the left-hand side of the shortest rule.

Returns the index of the left-hand side of the first rule in the presentation with minimal length. The length of a rule is defined to be the sum of the lengths of its left-hand and right-hand sides.

Parameters:

p (Presentation) – the presentation.

Returns:

the index of the rule.

Return type:

int

Raises:

LibsemigroupsError – if the length of p.rules is odd.

presentation.shortest_rule_length(p: Presentation) int

Return the minimum length of a rule in the presentation.

Returns the minimum length of a rule in the presentation. The length of a rule is defined to be the sum of the lengths of its left-hand and right-hand sides.

Parameters:

p (Presentation) – the presentation.

Returns:

the length of the shortest rule

Return type:

int

Raises:

LibsemigroupsError – if the length of p.rules is odd.

presentation.sort_each_rule(*args, **kwargs)

Overloaded function.

presentation.sort_each_rule(p: Presentation) bool

Sort the left-hand and right-hand side of each rule by shortlex.

Sort each rule \(u = v\) so that the left-hand side is shortlex greater than the right-hand side, and return True if any of the rules are changed.

Parameters:

p (Presentation) – the presentation whose rules should be sorted.

Returns:

whether any of the rules were changed.

Return type:

bool

Raises:

LibsemigroupsError – if p.rules.size() is odd.

Complexity:

Linear in the number of rules.

presentation.sort_each_rule(p: Presentation, cmp: collections.abc.Callable[[Word, Word], bool]) bool

Sort the left-hand and right-hand side of each rule relative to cmp.

Sort each rule \(u = v\) so that the left-hand side is greater than the right-hand side with respect to cmp, and return True if any of the rules are changed.

Parameters:
  • p (Presentation) – the presentation whose rules should be sorted.

  • cmp (collections.abc.Callable[[Word, Word], bool]) – the comparison function.

Returns:

whether any of the rules were changed.

Return type:

bool

Raises:

LibsemigroupsError – if p.rules.size() is odd.

Complexity:

Linear in the number of rules.

presentation.sort_rules(p: Presentation) None

Sort all of the rules by shortlex.

Sort the rules \(u_1 = v_1, \ldots, u_n = v_n\) so that \(u_1v_1 < \cdots < u_nv_n\) where \(<\) is the shortlex order.

Parameters:

p (Presentation) – the presentation to sort.

Raises:

LibsemigroupsError – if p.rules.size() is odd.

presentation.strongly_compress(p: Presentation) bool

Strongly compress a one relation presentation.

Strongly compress a one relation presentation. Returns True if the one relation presentation p has been modified and False if not. The word problem is solvable for the input presentation if it is solvable for the modified version.

Parameters:

p (Presentation) – the presentation.

Returns:

whether or not the presentation has been modified.

Return type:

bool

presentation.throw_if_bad_inverses(p: Presentation, vals: Word) None

Validate if vals act as semigroup inverses in p.

Check if the values in vals act as semigroup inverses for the letters of the alphabet of p. Specifically, it checks that the \(i\)-th value in vals acts as an inverse for the \(i\)-th value in p.alphabet().

Let \(x_i\) be the \(i\)-th letter in p.alphabet(), and suppose that \(x_i=v_j\) is in the \(j\)-th position of vals. This function checks that \(v_i = x_j\), and therefore that \((x_i^{-1})^{-1} = x\).

Parameters:
  • p (Presentation) – the presentation.

  • vals (Word) – the values to check if the act as inverses.

Raises:
presentation.to_gap_string(p: Presentation, var_name: str) str

Return the code that would create p in GAP.

This function returns the string of GAP code that could be used to create an object with the same alphabet and rules as p in GAP. Presentations in GAP are created by taking quotients of free semigroups or monoids.

Parameters:
  • p (Presentation) – the presentation.

  • var_name (str) – the name of the variable to be used in GAP.

Returns:

the GAP string.

Return type:

str