Print methods in the permutations package

Robin K. S. Hankin

To cite the permutations package in publications, please use Hankin (2020). The permutations package has a print method which includes a number of user-configurable options which are illustrated and motivated here.

Permutations have two natural representations: word form and cycle form. Internally, the package coerces a permutation from one form to another depending on what operations one does with it. Group-theoretic products and inverses are carried out more easily in word form, while powers are more easily done using cycle form.

Partly as a result of a perceptive comment from a journal reviewer, the package coerces to cycle form for printing as this is generally more comprehensible than word form. However, the package print method is extensively customizable. This document covers some of the options. Low-level print functionality includes print_word() and print_cycle() which can be used explicitly to print in either word form or cycle form as desired:

set.seed(0)
x <- rperm(r = 9)
print_word(x)
#>      1 2 3 4 5 6 7 8 9
#> [1]  9 4 7 1 2 . 3 . 5
#> [2]  2 3 8 1 . . 9 7 4
#> [3]  7 1 9 5 6 8 4 2 3
#> [4]  5 . 8 6 1 4 3 9 7
#> [5]  3 6 2 7 4 5 8 9 1
#> [6]  7 6 1 . 9 3 2 . 5
#> [7]  3 . 6 7 8 1 5 9 4
#> [8]  6 1 . 7 4 2 9 . 5
#> [9]  4 5 1 7 9 3 6 . 2
#> [10] 6 5 4 7 1 8 9 3 2
print_cycle(x)
#>  [1] (19524)(37)    (1238794)      (1745682)(39)  (15)(3897)(46) (132654789)   
#>  [6] (17263)(59)    (136)(47589)   (162)(4795)    (14763)(259)   (168347925)

It is a matter of taste which one is preferable. For the example above, the majority of the symbols are moved: elements that map to themselves are shown with a dot in the word form, and these are in a minority. However, the difference between word form and cycle form becomes more pronounced if only a small number of elements move:

x <- rperm(r = 9, moved = 3)
print_word(x)
#>      1 2 3 4 5 6 7 8 9
#> [1]  7 . . . . . 9 . 1
#> [2]  . 9 2 . . . . . 3
#> [3]  . . . . . . . . .
#> [4]  3 . 1 . . . . . .
#> [5]  . 8 . . 2 . . 5 .
#> [6]  . . . 6 . 4 . . .
#> [7]  . . . . . . . . .
#> [8]  . . . 8 . . . 4 .
#> [9]  6 . 1 . . 3 . . .
#> [10] . . . 9 . . . . 4
print_cycle(x)
#>  [1] (179) (293) ()    (13)  (285) (46)  ()    (48)  (163) (49)

Above we see the cycle form is arguably more compact.

Cycles in length order

Consider the following:

options(perm_set = NULL) # revert to numbers
options(comma = FALSE) # supress comma
x <- rgivenshape(30, 2:4)
x
#>  [1] (1938)(256)(47) (162)(3547)(89) (189)(24)(3567) (1523)(48)(697)
#>  [5] (163)(25)(4978) (1263)(45)(789) (1829)(36)(457) (1764)(239)(58)
#>  [9] (153)(28)(4976) (1783)(265)(49) (1829)(34)(576) (13)(2496)(587)
#> [13] (1326)(498)(57) (1537)(286)(49) (17)(284)(3965) (1846)(237)(59)
#> [17] (1597)(246)(38) (1392)(486)(57) (17)(268)(3549) (1972)(356)(48)
#> [21] (198)(2647)(35) (14)(2853)(697) (19)(247)(3568) (1458)(29)(367)
#> [25] (1249)(367)(58) (1794)(256)(38) (1394)(287)(56) (167)(2439)(58)
#> [29] (15)(287)(3649) (1369)(285)(47)

We see 30 random permutations with shape \(\left(\cdot\,\cdot\right)\left(\cdot\cdot\cdot\right)\left(\cdot\cdot\cdot\right)\). However, because function nicify_cyclist() sorts each cycle so that the smallest element is first, then sorts the cycles by first element, it is not obvious that all the permutations above have the same shape. The print method is sensitive to experimental option print_in_length_order (via function as.character_cyclist()). If TRUE, permutations cycle form will be printed but with the cycles in increasing length order:

options("print_in_length_order" = TRUE)
x
#>  [1] (47)(256)(1938) (89)(162)(3547) (24)(189)(3567) (48)(697)(1523)
#>  [5] (25)(163)(4978) (45)(789)(1263) (36)(457)(1829) (58)(239)(1764)
#>  [9] (28)(153)(4976) (49)(265)(1783) (34)(576)(1829) (13)(587)(2496)
#> [13] (57)(498)(1326) (49)(286)(1537) (17)(284)(3965) (59)(237)(1846)
#> [17] (38)(246)(1597) (57)(486)(1392) (17)(268)(3549) (48)(356)(1972)
#> [21] (35)(198)(2647) (14)(697)(2853) (19)(247)(3568) (29)(367)(1458)
#> [25] (58)(367)(1249) (38)(256)(1794) (56)(287)(1394) (58)(167)(2439)
#> [29] (15)(287)(3649) (47)(285)(1369)

Wrapup

Above we used state abbreviations (a builtin R dataset) and also direct the print method to use commas for readability. However, it is best to reset to the default, as the option persists between vignettes:

options(perm_set = NULL)
options(comma = NULL)
options(print_word_as_cycle = FALSE)
options("print_in_length_order" = FALSE)

References

Hankin, R. K. S. 2020. “Introducing the Permutations R Package.” SoftwareX 11. https://doi.org/10.1016/j.softx.2020.100453.