This third paper on ribbon graphs, after [10] and [11], presents an algorithm to enumerate their partial duals according to Euler-genus. This algorithm applies to several partial dualities and trialities, not just to partial Poincaré duality. We assume some familiarity with the fundamentals of graph embeddings beyond planarity issues, as presented, for instance, by [13] or [22], and also with ribbon graphs, as described by [9]. Prior familiarity with flags and monodromy would be helpful, but is not assumed.

The algorithm has three principal procedures:

  • The initialization procedure has as input parameters the number N of edges of a ribbon graph G and a uni-rotation system W for G. A uni-rotation is roughly describable as a cycle of quarter-edges (or equivalently, of flags) incident at a vertex. From this information, the procedure constructs what we call an extended monodromy module comprising the monodromy and some additional information about the embedding it represents.

  • The main procedure examines all the partial duals of G, conceptualized as the nodes of a hypercube. At each node, it updates the current module, so that it specifies the next partial dual along a Gray code, and it passes some data to a procedure that calculates the Euler-genus into a running count of the occurrences of Euler-genus values.

  • The Euler-genus procedure has as input parameters the number of edges of G and the bi-rotations for vertices and faces of the current partial dual. A bi-rotation is roughly described as a pair of cycles, each of which represents a direction of traversal of a set of edges.

In Sect. 1, we review the definitions of graphs, graph embeddings, rotation systems and ribbon graphs. Section 2 briefly reviews flags and the monodromy paradigm for specifying a graph embedding and resolves their relation to ribbon graphs. In Sect. 3, we review the duality and triality operators on a graph embedding. Section 4 describes the corresponding partial operators and the polynomials that enumerate the partial duals. Section 5 presents the algorithm for calculating the polynomials. We have used a \(\hbox {Maple}^{\textregistered }\) implementation of our algorithm as an experimental research aid in developing the content of [10] and [11].

Italics on various technical terms indicates that their definitions or relevant descriptions appear later, usually along with some developmental detail.

1 Introduction

In general, we allow a graph to have loops and multi-edges. Each edge is construed to have two half-edges (that meet midway along the length of the edge). We label the edges of a graph by the integers \(\varvec{1,2,\ldots ,n}\). A direction of traversal of an edge may be given by specifying the half-edge that is traversed last (where a traversal in that direction terminates). If we are specifying graph embeddings by traditional rotation systems or by ribbon graphs, we may denote the half-edges of edge j by \(\varvec{j^+}\) and \(\varvec{j^-}\). However, if specification involves monodromy, then a half-edge corresponds to the two flags incident on that half-edge. A graph is taken to be connected, unless it is evident from context that we mean otherwise.

All embeddings are cellular, so that the interior of every region is homeomorphic to an open disk. The genus of an orientable surface \({\varvec{S}}\) is denoted by \(\varvec{\gamma (S)}\). The orientable surface of genus \({\varvec{j}}\) is denoted \(\varvec{S_j}\) and the non-orientable surface of crosscap number \({\varvec{k}}\) is denoted \(\varvec{N_k}\).

The word map is a synonym for “graph embedding”. Writing \(\varvec{Map(G)}\) is simply an explicit way to emphasize the embedding, rather than the underlying graph.

Rotation systems and monodromy are the two forms of combinatorial specification of a graph embedding that are used within our algorithm for calculating partial-dual polynomials. In this section, we briefly review rotation systems and ribbon graphs. In the next section, we explain why our algorithm uses both rotation systems and monodromy.

Notational Conventions. For any two permutations \(\alpha \) and \(\beta \) of the same set of objects, the notation \(\varvec{\alpha \beta }\) indicates the composition in which \(\alpha \) is applied before \(\beta \). Also, we use \(\varvec{|\alpha |}\) to denote the number of cycles in a permutation \(\alpha \).

1.1 Rotation systems

For an oriented embedding of a graph G, the induced rotation at a vertex v, commonly denoted by \(\varvec{\rho _v}\), is a cyclic permutation of the half-edges incident at v, in the order consistent with the orientation of the surface. In the context of rotations, we define the permutation \(\varvec{\lambda }\) on the half-edges of a graph G to be the involution that transposes a half-edge of an edge e with the other half-edge of e. The composition \(\rho \,=\,\Pi _{v\in V(G)}\rho _v\) is called the induced rotation system for G. It is commonly denoted by \(\varvec{\rho }\). Within the monodromy paradigm, the meanings of the notations \(\lambda \) and \(\rho \) are a little different.

Conversely, given a graph G, we might specify at every vertex v an arbitrary cyclic permutation \({\overline{\rho }}_v\) of the half-edges incident at v, and then call \({\overline{\rho }} \,=\,\Pi _{v\in V(G)} {\overline{\rho }}_v\) an assigned rotation system. It is well-known that an assigned rotation system induces an oriented embedding of G, in which the cycles of the permutation \({\overline{\rho }}\lambda \) trace the face-boundary walks of an oriented embedding of G. This is constructed by fitting a polygon with the appropriate number of sides to each of those cycles. We have the following immediate implication:

Proposition 1.1

The total number of oriented embeddings of a graph G equals

$$\begin{aligned} \prod _{v\in V(G)} (\delta (v)-1)! \end{aligned}$$
(1.1)

where V(G) is the vertex set of G and \(\delta (v)\) is its valence (or degree). \(\square \)

1.2 Ribbon graphs

A ribbon graph can be specified as a set of disks called vertex disks and a set of rectangular strips called ribbons (or sometimes, “edges”), such that each of the two ends of each ribbon is attached to a vertex disk along an arc; no two of these arcs meet. The same mathematical object was previously called a band decomposition by [13]. We implicitly associate to a ribbon graph a set of polygonal disks called face disks, one for each boundary component, and we envision the boundary circuit of each face disk as pasted homeomorphically to the corresponding boundary component. The visually evocative terminology “ribbon graph” appears to have originated with [19].

Figure 1 shows a ribbon graph with two vertex disks and five ribbons. It has become customary to label the ribbons with consecutive positive integers, as illustrated in this figure.

Fig. 1
figure 1

A ribbon graph with two vertex disks and five ribbons

Like some of our predecessors in the investigation of partial duals, we sometimes leave it to the reader to infer whether a particular occurrence of the phrase “ribbon graph” includes the face disks or not. For instance, the faces disks are absent (at least, momentarily) when we give a ribbon an extra half-twist. However, when we refer to the “Euler-genus of a ribbon graph”, we include the face disks. By tracing along the boundary of the ribbon graph in Fig. 1, we see that there is only one boundary component. Thus, saying that its Euler-genus is four means that the embedding surface has Euler-genus four.

Our present objective is to facilitate calculation of the Euler-genus of the partial duals of a ribbon graph, continuing the approach of [10] and [11]. We present a Gray code algorithm to calculate the partial-dual polynomials that provide an inventory of the partial duals of a ribbon graph, according to Euler-genus, for each of the duality operators: Poincaré duality \((*)\), Petrie duality \((\times )\), and Wilson duality \((*{\times }*)\). Our algorithm is loopless, with execution time \(\theta (2^n)\) for an n-edge graph.

Example 1.2

Let G be the 5-edge ribbon graph of Fig. 1. The Poincaré, Petrie, and Wilson partial-dual polynomials are, respectively,

$$\begin{aligned} ^\partial {{\mathscr {E}}}_G^*(z)= & {} 2z^2 + 6z^3 + 16z^4 + 8z^5, \\ ^\partial {{\mathscr {E}}}_G^\times (z)= & {} 5z^2 + 15z^3 + 12z^4, \hbox { and }\\ ^\partial {{\mathscr {E}}}_G^{*\times *}(z)= & {} 2z^3 + 13z^4 + 17z^5. \end{aligned}$$

These partial-duality polynomials were calculated by computer. An effort to calculate any of them by hand indicates the benefit of automated calculation, even for such a small ribbon graph. In [10] and [11], we have used analytic methods involving symmetries and recursions to derive partial-duality polynomials for ladder graphs, bouquets, dipoles, and cycle graphs.

2 Quarter-ribbons, flags, and monodromy

In this section, we describe a scheme for assigning flag labels. We see subsequently how this flag-labeling scheme simplifies calculations based on the monodromy.

2.1 Flags and quarter-ribbons, and monodromy

Figure 2 illustrates the decomposition of Map(G) into flags in the vicinity of an edge that has been designated as edge k. There are several steps to this decomposition.

Fig. 2
figure 2

The four quarter-ribbons of ribbon k, labeled as shown, along with four adjacent flags pqrs

Given an n-ribbon graph G, we construct the barycentric subdivision of Map(G), as described in [11]. Each face of Bary(G) is called a flag. The four flags incident on ribbon k induce a decomposition into four quarter-ribbons, to which we assign the canonical labels

$$\begin{aligned} 4k{-}3,\ 4k{-}2,\ 4k{-}1,\ \hbox { and }4k, \end{aligned}$$

as illustrated in Fig. 2, for \(k = 1, 2, \ldots , n\). In turn, assigning to each flag the same label as its quarter-ribbon is called the canonical labeling of the flags.

The monodromy of a ribbon graph G consists of three full involutions \(r_0\), \(r_1\), and \(r_2\), which are usually said to act on the flags of Map(G). We will say, equivalently, that they act on the quarter-ribbons.

$$\begin{aligned}&r_0 \quad \text {transposes any two quarter-ribbons on the same side of an edge.} \nonumber \\&\qquad \text {In Fig. }2, r_0\text { includes the 2-cycles }(4k{-}3,\ 4k{-}2) \text { and }(4k{-}1,\ 4k). \end{aligned}$$
(2.1)
$$\begin{aligned}&r_1 \quad \text {transposes any two quarter-ribbons in the same corner of } Map(G).\nonumber \\&\qquad \text {including }(p,\, 4k{-}3), (q,\, 4k{-}2), (r,4k{-}1), \text {and }(s, 4k). \end{aligned}$$
(2.2)
$$\begin{aligned}&r_2 \quad \text {transposes any two quarter-ribbons that share a half-ribbon of }G.\nonumber \\&\qquad \text {In Fig. }2, r_2 \text { includes the 2-cycles }(4k{-}3,\ 4k) \text { and }(4k{-}2,\ 4k{-}1). \end{aligned}$$
(2.3)

When \(r_0\) and \(r_2\) correspond to a canonical quarter-ribbon labeling, the triple \(\langle r_0, r_1, r_2 \rangle \) is called a canonical monodromy. We observe that the involutions \(r_0\) and \(r_2\) commute. A convenient accessory to the monodromy of a ribbon graph is the composite involution lambda \(\varvec{\lambda }\,=\,r_0r_2\).

Remark 2.1

In the context of rotation systems, the notation \(\lambda \) designates an involution that transposes the half-edges of each edge. In the context of monodromy, it designates an involution that transposes two pairs of quarter-ribbons for each edge.

Two of the involutions for the monodromy of any embedded graph G whose map has the canonical flag labeling are always of the same form. For the ribbon graph of Fig. 1 with five edges, or for any other graph with five edges, we have

$$\begin{aligned} r_0= & {} (1\ 2)(3\ 4)(5\ 6)(7\ 8)(9\ 10)(11\ 12)(13\ 14)(15\ 16)(17\ 18)(19\ 20). \end{aligned}$$
(2.4)
$$\begin{aligned} r_2= & {} (1\ 4)(2\ 3)(5\ 8)(6\ 7)(9\ 12)(10\ 11)(13\ 16)(14\ 15)(17\ 20)(18\ 19). \end{aligned}$$
(2.5)

Since \(\lambda \,=\,r_0r_2\), we also have

$$\begin{aligned} \lambda= & {} (1\ 3)(2\ 4)(5\ 7)(6\ 8)(9\ 11)(10\ 12)(13\ 15)(14\ 16)(17\ 19)(18\ 20). \end{aligned}$$
(2.6)

Example 2.2

To write the involution \(r_1\) for Fig. 1, we draw it with quarter-edge labeling, as shown in Fig. 3. From the corners of either the ribbon graph (left) or of its rotation projection (right), as defined by [13, §3.2.5], we read the involution

$$\begin{aligned} r_1= & {} (1\ 12)(2\ 6)(3\ 16)(4\ 13)(5\ 20)(7\ 9)(8\ 11)(10\ 18)(14\ 17)(15\ 19). \end{aligned}$$
(2.7)
Fig. 3
figure 3

(left) Quarter-ribbon labeling on the ribbon graph of Fig. 1. (right) A rotation projection of that ribbon graph

2.2 Face bi-rotations and vertex bi-rotations

Tracing along the boundary of the ribbon graph in Fig. 3, we can record the following cyclic sequence of quarter-ribbons encountered as the traversal (starting clockwise at quarter-edge 1) reaches the end of a ribbon:

$$\begin{aligned} 1,\ 11,\ 7,\ 10,\ 17,\ 13,\ 3,\ 15,\ 20,\ 6. \end{aligned}$$
(2.8)

Since the traversal (2.8) traces both sides of each of the five ribbons, this must be the boundary walk of the only face of the embedding. Since there are two vertices and five edges, we can now calculate the Euler characteristic of the embedding as

$$\begin{aligned} \chi \,=\,2 - 5 + 1 \,=\,-2. \end{aligned}$$

Since the embedding is non-orientable, we recognize the surface as \(N_4\), the surface with four crosscaps. An alternative way to calculate this face-boundary walk is via the composition \(r_1 r_0\), using (2.4) and (2.7).

$$\begin{aligned} r_1 r_0 \,=\,(1\;\ 11\;\ 7\;\ 10\;\ 17\;\ 13\;\ 3\;\ 15\;\ 20\;\ 6)(2\;\ 5\;\ 19\;\ 16\;\ 4\;\ 14\;\ 18\;\ 9\;\ 8\;\ 12) \end{aligned}$$
(2.9)

We see that the second 10-cycle of ribbons traversed corresponds to the first 10-cycle in reverse order, and we call these two cycles reverse face-boundary walks, or in context, inverse cycles. We call (2.9) a face bi-rotation, and we denote the composition \(r_1r_0\) by \(\varvec{\phi }\).

In a dual sense, tracing clockwise around the boundaries of the vertex disks u and v, we record these cyclic sequences of quarter-ribbons that are encountered:

$$\begin{aligned}&u.\quad 1,\ 9,\ 6,\ 3,\ 13 \end{aligned}$$
(2.10)
$$\begin{aligned}&v.\quad 5,\ 17,\ 15,\ 18,\ 11 \end{aligned}$$
(2.11)

These cyclic sequences are a flag-based representation of what are traditionally called rotations. An alternative way to calculate these rotations employs the composition \(r_1r_2\), using (2.7) and (2.5).

$$\begin{aligned} r_1 r_2 \,=\,(1\;\ 9\;\ 6\;\ 3\;\ 13)(2\;\ 7\;\ 12\;\ 4\;\ 16)(5\;\ 17\;\ 15\;\ 18\;\ 11)(8\;\ 10\;\ 19\;\ 14\;\ 20) \end{aligned}$$
(2.12)

We observe that this composition includes two additional 5-cycles, which correspond to quarter-ribbon cycles (2.10) and (2.11) in the opposite direction. We call the composition of the cycles (2.10) and (2.11) a vertex uni-rotation. We call the quarter-ribbon permutation (2.12) a vertex bi-rotation, and we denote it by \(\varvec{\rho }\).

Remark 2.3

An n-vertex ribbon graph G has \(2^n\) possible choices of a vertex uni-rotation, each of which corresponds to the choice of a spanning tree. We could draw a (rotation-preserving) planar projection of G so that each ribbon of the spanning tree is drawn flat, that is, with no twist. However, what simplifies the use of our algorithm is that, no matter which of these \(2^n\) possible uni-rotations we supply as input data, the initialization procedure (Algorithm 5.2) will construct the same bi-rotation.

Proposition 2.4

Let \(\psi \) be a vertex uni-rotation consistent with the canonical monodromy \(\langle r_0, r_1, r_2 \rangle \) for a ribbon graph G. Then

  1. (a)

    \(\rho \,=\,\psi (r_2\psi r_2)^{-1}\) is the corresponding vertex bi-rotation.

  2. (b)

    \(\phi \,=\,\rho \lambda \) is the corresponding face bi-rotation.

  3. (c)

    \(r_1 \,=\,\rho r_2.\)

Proof

This is straightforward.

  1. (a)

    \((r_2\psi r_2)^{-1}\) is evidently the composition of the cycles that are inverses to the cycles of \(\psi \).

  2. (b)

    Since \(\lambda = r_2r_0\) and \(\rho =r_1r_2\), we can employ this sequence of substitutions:

    $$\begin{aligned} \phi \,=\,r_1r_0 \,=\,r_1(r_2\lambda ) \,=\,(r_1r_2)\lambda \,=\,\rho \lambda . \end{aligned}$$
  3. (c)

    Since \(\rho = r_1r_2\), we have \(\rho r_2= r_1\).

\(\square \)

It is sometime convenient to use the phrase extended monodromy to refer to a collection of permutations that, in addition to \(r_0\), \(r_1\), and \(r_2\), also includes some additional permutations, such as \(\lambda \), \(\rho \) ,and \(\phi \).

2.3 Why we use two forms of embedding specification

In Sects. 4 and 5, we show how to change the extended monodromy of any partial dual of an embedded graph G to the extended monodromy of the next partial dual in the Gray code, by applying permutation compositions in Table 1. This is easier than trying to make the change with rotation systems alone. On the other hand, it is half as much effort to specify the initial embedding with a uni-rotation, which involves mentioning only half the quarter-edges, than to specify an involution of the monodromy, which requires writing all the quarter-edges (twice the effort, even though, using a canonical monodromy, specifying only \(r_1\) is sufficient.)

Table 1 Effect of partial-duality operators on the monodromy

3 Ribbon graphs and their dualities

Given an embedding (called the primal embedding) of a graph in a surface, we form a Poincaré dual of G and its embedding as follows:

  1. (1)

    place a dual vertex in the interior of each region of the primal embedding;

  2. (2)

    through each primal edge e (i.e., of the graph G), draw a dual edge \(\varvec{e^*}\) that joins the dual vertex on one side of e to the dual vertex on its other side. If a single face of the primal embedding is incident on both sides of edge e, then the dual edge \(e^*\) is a loop.

According to [2], knowledge of the duality between the cube and the octahedron, and between the dodecahedron and the icosahedron goes back to the “fifteenth book of Euclid”, which [2] estimates as having originated in the sixth century C.E. Poincaré developed algebraic consequences of a generalization of this topological form of duality to higher dimensions.

Corollary 3.1

The rotation system for the Poincaré dual of an embedding with rotation system \(\rho \) is given by the composition \(\rho \lambda \). \(\square \)

We recall that the full Poincarè dual \(G^*\) of an embedded graph G (referred to as the “primal” graph) is constructed as follows:

  1. (1)

    Into the interior of each primal face, a dual vertex is inserted.

  2. (2)

    Through each primal edge, a dual edge is drawn that joins the dual vertex on one side of that primal edge to the dual vertex on the other side. If both sides of the primal edge lie on the same primal face, then the dual vertex in that face is joined to itself.

A completely topological definition of a Poincaré partial dual on an edge subset A, here denoted by \(G^{*|_A}\), was given by Chmutov [5] (see also [9]), and is not reproduced here. Here, as in [11], we represent the Poincaré dual and partial dual by combinatorial operations on the monodromy.

The Petrie dual \(G^\times \) of a ribbon graph G is constructed by detaching one end of each ribbon at the arc where it meets a vertex disk, giving that ribbon an extra half-twist, and then reattaching the end at the same vertex disk arc. For any set A of ribbons of G, there is a topological construction of the partial Petrie dual on A, denoted \(G^{\times |A}\) by applying that half-twist operation only to the ribbons in A. Here we represent the Petrie dual and partial dual by combinatorial operations on the monodromy.

Wilson [23] showed that under composition, the duality operators \(*\) and \(\times \) form a group of order six, now called the Wilson group, with the presentation

$$\begin{aligned} {\mathcal {G}} \,=\,\langle *, \times \mid *^2\!,\, \times ^2\!,\, (*\times )^3 \rangle \end{aligned}$$

and is abstractly isomorphic to the symmetric group \(\Sigma _3\). Since its order is three, the composite operator \(*\times \) is called a triality. It is easily proved that the composite operator \(\times *\) is also a triality and that \((*\times )^2 = \times *\). The operator \(*{\times }*\) is of order two and is often called the Wilson dual or the Wilsonian.

Abrams and Ellis-Monaghan [1] have introduced the word twualities to refer to the three dualities and the two trialities collectively.

4 Partial-twuality polynomials

The Euler-genus of a ribbon graph G is given by the formula

$$\begin{aligned} {{\mathfrak {e}}}(G) \,=\,2 - \big (|V(G)| - |E(G)| + |F(G)|\big ), \end{aligned}$$
(4.1)

where V(G) is the set of vertex disks, E(G) is the set of ribbons (edges), and F(G) is the set of face disks. Every partial dual of a ribbon graph G has the same number of ribbons as G itself. Thus, to calculate the Euler-genus of some partial dual of G, it is sufficient, in view of Proposition 2.4, to know the monodromy of that partial dual, since

$$\begin{aligned} |V(G)|=\frac{|r_1r_2|}{2}\ \hbox { and }\ |F(G)|=\frac{|r_1r_0|}{2}. \end{aligned}$$
(4.2)

Table 1 (reproduced from [11, Table 3.1]) is our guideline to calculating the partial dual of any ribbon graph for any twuality. The symbols s and t in the labels for columns \(r_0^{\bullet |_A}\) and \(r_2^{\bullet |_A}\) are generic names for the various right multipliers of \(r_0\) and \(r_2\) that appear to the right of the equals sign in the entries within those respective columns.

The partial-duality polynomial of the ribbon graph G for each of the twualities is the polynomial for which the coefficient of \(z^r\) is the number of partial duals of G whose Euler-genus is r. It follows that if G has n ribbons, then, since the number of subsets of ribbons is \(2^n\), it follows that the sum of those coefficients is \(2^n\). The five partial-duality polynomials of G are denoted

$$\begin{aligned} ^\partial {{\mathscr {E}}}_G^*(z),\ ^\partial {{\mathscr {E}}}_G^\times (z),\ ^\partial {{\mathscr {E}}}_G^{*\times }(z),\ ^\partial {{\mathscr {E}}}_G^{\times *}(z),\ \hbox { and }\ ^\partial {{\mathscr {E}}}_G^{*\times *}(z). \end{aligned}$$

Example 4.1

As an example of a monodromy-based calculation, we calculate the Euler-genus of the Petrie partial dual on ribbons 1 and 3 of the quarter-ribbon labeled ribbon graph G in Fig. 4.

Fig. 4
figure 4

A ribbon graph with quarter-ribbon labeling

We can see immediately that there is one vertex and that there are three ribbons. For this very small example, we could easily draw the designated Petrie partial dual by twisting ribbon 1 and untwisting ribbon 3 and then doing face-tracing by hand to determine that there is only one face. Thus, we now know that \({{\mathfrak {e}}}(G^{\times |_A}) = 3\), that is, the Euler-genus of the partial dual is three.

The ribbon graph G has as a vertex uni-rotation the cyclic permutation

$$\begin{aligned} (1\ 10\ 6\ 9\ 3\ 5), \end{aligned}$$

to which an automated procedure could apply Proposition 2.4, thereby to obtain the vertex bi-rotation and the face bi-rotation

$$\begin{aligned} \rho \,=\,(1\ 10\ 6\ 9\ 3\ 5)(2\ 12\ 7\ 11\ 4\ 8) \\ \phi \,=\,(1\ 12\ 5\ 3\ 7\ 9)(2\ 10\ 8\ 4\ 6\ 11), \end{aligned}$$

and the (extended) monodromy

$$\begin{aligned} r_0= & {} (1\ 2)(3\ 4)(5\ 6)(7\ 8)(9\ 10)(11\ 12) \\ r_2= & {} (1\ 4)(2\ 3)(5\ 8)(6\ 7)(9\ 12)(10\ 11) \\ r_1= & {} (1\ 11)(2\ 9)(3\ 8)(4\ 5)(6\ 12)(7\ 10) \\ \lambda= & {} (1\ 3)(2\ 4)(5\ 7)(6\ 8)(9\ 11)(10\ 12). \end{aligned}$$

To obtain the face bi-rotation for \(G^{\times |_{\{1,3\}}}\), for instance, we evaluate Table 1 entry in Row \(G^{\times |_A}\), Column \(\phi r_2^{\bullet |_A}\) for \(A\,=\,\{1,3\}\).

$$\begin{aligned} \phi r_2|_{\{1,3\}}= & {} (1\ 9\ 4\ 6\ 10\ 8) (2\ 11\ 3\ 7\ 12\ 5) \end{aligned}$$

Since the face bi-rotation has two cycles, the number of faces is one.

5 Algorithm for partial-twuality polynomials

For a given partial-twuality operator \(\bullet \), in order to use (4.2) to calculate the partial-duality polynomial \(^\partial {{\mathscr {E}}}_G^{\bullet }\), we need to calculate the vertex bi-rotation \(\rho ^{\bullet |_A}\) and face bi-rotation \(\phi ^{\bullet |_A}\) of the partial dual \(G^{\bullet |_A}\), for every ribbon subset \(A\subseteq E(G)\). To accomplish this, we conceptually identify the ribbon subsets with the nodes of the standard Boolean lattice of subsets of \(\{1, 2, \ldots , n\}\), where \(|E(G)|=n\). Each ribbon e of G is identified with one of the n ordered bits. This identifies each node of the n-cube with some integer from 0 to \(2^n -1\), as well as with a ribbon subset. With that in mind, calculating the inventory of partial duals is a straightforward matter of traversing the n-cube, while doing the following at each node:

  1. (1)

    update the monodromy for the partial dual represented by the node just encountered;

  2. (2)

    calculate the numbers of vertex disks and face disks for the ribbon graph specified by that monodromy;

  3. (3)

    calculate the Euler-genus of the corresponding embedding, and increment the corresponding counter.

We modularize our algorithm, so that initialization and the calculation of Euler-genus are given as separate procedures.

Pseudocode Conventions. We specify algorithms in an informal pseudocode, which somewhat resembles \(\hbox {Maple}^{\textregistered }\).

  • By default, program variables (not including input and output parameters) are local. Their data types (e.g., integer, character string, permutation, array) are usually inferred from context.

  • The index of a subscripted variable is understood as a coordinate in an array. The default base coordinate of an array is zero.

  • For emphasis, we sometimes write instructions that assign a variable its default value.

  • Boldface is used for clarity; no other meaning is intended.

  • In the pseudocode, for any two permutation-valued variables \(\alpha \) and \(\beta \) of the same set of objects, the notation \({\alpha \!\cdot \!\beta }\) indicates the composition in which \(\alpha \) is applied before \(\beta \). This is opposite to the meaning of juxtaposition in prose.

5.1 Gray code traversal of the n-cube

A Gray code for the n-cube is a permutation of the non-negative integers \(1, 2, \ldots , 2^n{-}1\), such that the binary representations of the Gray codes gray(k) and \(gray(k+1)\) of two successive integers differ in only one bit. For a ribbon graph G with ribbons labeled \(1, 2, \ldots , n\), each number

$$\begin{aligned} k \in \{0, 1, \ldots , 2^n{-}1\} \end{aligned}$$

stands for a subset of ribbons. The \(j^{\mathrm{th}}\) bit in the binary representation of gray(k) corresponds to ribbon j, and the number k corresponds to the subset of E(G) in which ribbon j is a member if and only if the \(j^{\mathrm{th}}\) bit of gray(k) is 1.

The \(0^{\mathrm{th}}\) number in our sequence of integers is \(gray(0)=0\). To find the next binary numeral after the binary numeral gray(k), we calculate lowbit(k) to be the lowest order 1-bit of the binary representation of \(k+1\), and we change that bit in the binary numeral gray(k).

Algorithm 5.1

(lowest bit of binary representation of number n)

  1. (1)

    \({\varvec{lowbit}}\ {:=} {\varvec{procedure}}(n) \)

  2. (2)

    \(j=0:\)

  3. (3)

    if \(n = 0\) then return (0) : end if :

  4. (4)

    while \(n ~\mathrm{mod}~2^j = 0\) do

  5. (5)

          \(j{:=} j+1:\) end do :

  6. (6)

    return(j) :  end proc :

Example 5.1

The following table presents the values of \(lowbit(k+1)\) and gray(k) for \(k\,=\,0,1,\ldots ,9\).

$$\begin{aligned} \begin{array}{ccccccccccccc} &{}k &{} 0 &{} 1 &{} 2 &{} 3 &{} 4 &{} 5 &{} 6 &{} 7 &{} 8 &{} 9 &{} \cdots \\ &{}lowbit(k+1) &{} 1 &{} 2 &{} 1 &{} 4 &{} 1 &{} 2 &{} 1 &{} 8 &{} 1 &{} 2 &{} \cdots \\ &{}gray(k) &{} 0 &{} 1 &{} 3 &{} 2 &{} 6 &{} 7 &{} 5 &{} 4 &{}12 &{}13 &{} \cdots \\ \end{array} \end{aligned}$$

5.2 Initialization procedure

The input parameters of our initialization procedure are the number of ribbons of the ribbon graph G and the vertex uni-rotation relative to a given spanning tree. The output parameter is an extended monodromy for G. The pound sign symbol “#” indicates a comment. The presumption of the last few lines is that everything is returned as a single module representing an extended monodromy. The composition of permutations \(\alpha \) and \(\beta \) is denoted by \(\alpha \!\cdot \!\beta \).

Algorithm 5.2

(transform a uni-rotation into an extended monodromy)

  1. (1)

    \({\varvec{ExtMono}} {:=}{\varvec{procedure}}(N, W)\)

  2. (2)

    ## parameter \({\varvec{N}}\) is number of ribbons of graph G, i.e., \(N=|E(G)|\)

  3. (3)

    ## parameter \({\varvec{W}}\) is uni-rotation for G

  4. (4)

    #

  5. (5)

    ## canonical involution \(r0[1..N] = (1, 2)(3,4)\ldots (4N{-}3,4N{-}2)(4N{-}1,4N)\)

  6. (6)

    \(r0_0 {:=} (\ ): \) # initialization

  7. (7)

    for j from 1 to N do # use canonical flag labels

  8. (8)

    \(r0_j {:=} (4j{-}3, 4j{-}2)(4j{-}1, 4j): \) end do:

  9. (9)

    #

  10. (10)

    ## canonical involution \(r2[1..N] = (1, 4)(2,3)\ldots (4N{-}3,4N)(4N{-}2,4N{-}1)\)

  11. (11)

    \(r2_0 {:=} (\ ): \) # initialization

  12. (12)

    for j from 1 to N do # use canonical flag labels

  13. (13)

    \(r2_j {:=} (4j{-}3, 4j)(4j{-}2, 4j{-}1): \) end do:

  14. (14)

    #

  15. (15)

    ## canonical involution \(\lambda [1..N] = (1,3)(2,4)\ldots (4N{-}3,4N{-}1)(4N{-}2,4N)\)

  16. (16)

    \(LAM {:=} (\ ): \) # initialization

  17. (17)

    for j from 1 to N do

  18. (18)

    \(\lambda _j {:=} r0_j\!\cdot \!r2_j:\)

  19. (19)

    \(LAM {:=} LAM\!\cdot \!\lambda _j:\) end do:

  20. (20)

    #

  21. (21)

    ## construct initial vertex bi-rotsys \(\rho \) and initial face bi-rotsys \(\phi \) via Prop 2.4

  22. (22)

    \(UR {:=} W:\)

  23. (23)

    for j from 1 to N do ## loop installs co-rotsys labels in UR

  24. (24)

    \(UR {:=} r2_j\!\cdot \!UR\!\cdot \!r2_j: \) end do:

  25. (25)

    \(\rho {:=} W\!\cdot \!UR^{-1}:\) # \(\rho \) is now vertex bi-rotsys

  26. (26)

    \(\phi {:=} \rho \!\cdot \!LAM:\) # \(\phi \) is now face bi-rotsys

  27. (27)

    #

  28. (28)

    ## construct extended monodromy module M and return

  29. (29)

    \(M_1 {:=} r0: \ M_2{:=} r_2: \ M_3{:=}\lambda : \ M_4{:=} \rho : \ M_5{:=} \phi : \)

  30. (30)

    \({{\varvec{return}}}(M): {{\textit{\textbf{end proc}}}}\):

5.3 Euler-genus of a ribbon graph

The input parameters of our procedure for calculating the Euler-genus of a ribbon graph G are the number of ribbons, the vertex bi-rotation, and the face bi-rotation of G. The output parameter is the Euler-genus.

Algorithm 5.3

(calculate the Euler-genus)

  1. (1)

    \({\varvec{EulerGenus}} {:=}{\varvec{procedure}}(N, \rho , \phi )\)

  2. (2)

    ## input parameter \({\varvec{N}}\) is number of ribbons of graph G, i.e., \(N=|E(G)|\)

  3. (3)

    ## input parameters \(\varvec{\rho }\) and \(\varvec{\phi }\) are vertex bi-rotation, face bi-rotation

  4. (4)

    #

  5. (5)

    \({\varvec{v}}{:=}|\rho |/2: \)   # number of cycles of \(\rho \) = twice number of vertices

  6. (6)

    \({\varvec{f}}{:=}|\phi |/2: \)    # number of cycles of \(\phi \) = twice number of faces

  7. (7)

    \(\varvec{\chi }{:=} v - N + f:\)    # Euler characteristic

  8. (8)

    \(\varvec{\varepsilon }{:=} 2-\chi : \)    # Euler-genus for CONNECTED ribbon graph

  9. (9)

    \({\varvec{return}}(\varvec{\varepsilon }): \ {\varvec{end proc}}: \)

5.4 A loopless algorithm for the partial-duality polynomial

A loopless algorithm is an imperative algorithm that generates an initial object in constant time, and then successive combinatorial objects, in linear time in the size of the input [7, 15]. It is clear that Algorithm 5.4 is loopless. The main loop traverses a Gray code in the hypercube of ribbon subsets of the ribbon graph G received as input.

The input parameters are the number N of ribbons of G, a vertex uni-rotation for G, and the duality operation \(\bullet \) of interest. Within the loop at the node j representing the ribbon subset A, it executes the following steps:

  1. (1)

    calculate the monodromy of the partial dual \(G^{\bullet |_A}\) represented by node j from the monodromy of the previous node, based on the permutation compositions indicated in Table 1;

  2. (2)

    calculate the Euler-genus \({{\mathfrak {e}}}(G^{\bullet |_A})\) of the ribbon graph corresponding to node j;

  3. (3)

    increment the counter for the coefficient of \(z^{{{\mathfrak {e}}}(G^{\bullet |_A})}\).

Algorithm 5.4

(partial-twuality polynomial for ribbon graph \({\varvec{G}}\))

  1. (1)

    PTwuPoly \({:=}{\varvec{procedure}}(N, W, TC)\)

  2. (2)

    ## input parameter \({\varvec{N}}\) is number of edges of G, i.e., \(N=|E(G)|\)

  3. (3)

    ## input parameter \({\varvec{W}}\) is uni-rotation for G

  4. (4)

    ## input parameter \(\varvec{TC}\) is code for operation \(*\), \(\times \), \(*{\times }*\), \(*\times \), or \(\times *\)

  5. (5)

    #

  6. (6)

    ### INITIALIZE

  7. (7)

    M:= ExtMono(N,W): # transform uni-rot W into extended monodromy M

  8. (8)

    \(r0{:=}M_1: \ r2{:=} M_2: \ \lambda {:=}M_3: \ \rho {:=}M_4: \ \phi {:=}M_5: \)

  9. (9)

    coeff:= vector(0..N, 0): # initialize coeffs of partial dual poly at zero

  10. (10)

    Gray:= vector(1..N, 0): # kludge used only for trialities \(*\times \) and \(\times *\)

  11. (11)

    #

  12. (12)

    ### MAIN LOOP: ACCUMULATE EULER-GENUS COUNTS

          while TRAVERSING GRAY CODE

  13. (13)

    for \(j{:=}0\) to \(2^N-1\) do

  14. (14)

       \({\varvec{if }} TC = *\) then \(\rho {:=}\rho \!\cdot \!\lambda _{lowbit(j)}: \ \phi {:=}\phi \!\cdot \!\lambda _{lowbit(j)}\)

          \(r0save{:=}r0_{lowbit(j)}: \ r0_{lowbit(j)}{:=}r2_{lowbit(j)}: \ r2_{lowbit(j)}{:=} r0save: \)

  15. (15)

       \({\varvec{elif }} TC = \times {\varvec{ then }} \ \phi {:=}\phi \!\cdot \!r2_{lowbit(j)}:\)

          \(r0save{:=}r0_{lowbit(j)}: \ r0_{lowbit(j)}{:=}\lambda _{lowbit(j)}: \ \lambda _{lowbit(j)}{:=} r0save: \)

  16. (16)

       \({\varvec{elif }} TC = *{\times *} {\varvec{ then }}\)

          \(\rho {:=}\rho \!\cdot \!r0_{lowbit(j)}\):

          \(r2save{:=}r2_{lowbit(j)}: \ r2_{lowbit(j)}{:=}\lambda _{lowbit(j)}: \ \lambda _{lowbit(j)}{:=} r2save:\)

  17. (17)

       \({\varvec{elif }} TC = *{\times } {\varvec{ then }} \)

  18. (18)

          \({\varvec{if}} j>0 {\varvec{and}} Gray_{lowbit(j)}=0 {\varvec{then}}\)

             \(\rho {:=}\rho \!\cdot \!\lambda _{lowbit(j)}: \ \phi {:=}\phi \!\cdot \!r2_{lowbit(j)}: r0save{:=} r0_{lowbit(j)}: \)

             \(r0_{lowbit(j)}{:=}\lambda _{lowbit(j)}: \ \lambda _{lowbit(j)}{:=}r2_{lowbit(j)}: \ r2_{lowbit(j)}{:=} r0save: \)

  19. (19)

          else

             \(\rho {:=}\rho \!\cdot \!r0_{lowbit(j)}: \ \phi {:=}\phi \!\cdot \!\lambda _{lowbit(j)}: r0save{:=} r0_{lowbit(j)}: \)

             \(r0_{lowbit(j)}{:=}r2_{lowbit(j)}: \ r2_{lowbit(j)}{:=}\lambda _{lowbit(j)}: \ \lambda _{lowbit(j)}{:=} r0save: \)

             end if

  20. (20)

       \({\varvec{elif }} TC = {\times }* {\varvec{ then }} \)

  21. (21)

          \({\varvec{if}} j>0 {\varvec{and}} Gray_{lowbit(j)}=0 {\varvec{then}}\)

             \(\rho {:=}\rho \!\cdot \!r0_{lowbit(j)}: \ \phi {:=}\phi \!\cdot \!\lambda _{lowbit(j)}: r0save{:=} r0_{lowbit(j)}: \)

             \(r0_{lowbit(j)}{:=}r2_{lowbit(j)}: \ r2_{lowbit(j)}{:=}\lambda _{lowbit(j)}: \ \lambda _{lowbit(j)}{:=} r0save: \)

  22. (22)

          else

             \(\rho {:=}\rho \!\cdot \!\lambda _{lowbit(j)}: \ \phi {:=}\phi \!\cdot \!r2_{lowbit(j)}: r0save{:=} r0_{lowbit(j)}: \)

             \(r0_{lowbit(j)}{:=}\lambda _{lowbit(j)}: \ \lambda _{lowbit(j)}{:=}r2_{lowbit(j)}: \ r2_{lowbit(j)}{:=} r0save: \)

             end if

  23. (23)

       else print(“INVALID DUALITY CODE”); return; # execution halts

             end if

  24. (24)

       ## the vector Gray is a kludge used only for trialities \(*\times \) and \(\times *\)

  25. (25)

       \({\varvec{if}} j>0 {\varvec{then}} Gray_{lowbit(j)}{:=} (Gray_{lowbit(j)}+1) {\varvec{mod}} 2: {\varvec{end if:}}\)

  26. (26)

       ## CALCULATE and RECORD EULER-GENUS

  27. (27)

       \(\varepsilon {:=} {\varvec{EulerGenus}}(N,\rho ,\phi )\):

  28. (28)

       \(\hbox {coeff}_{\varepsilon } {:=} \hbox {coeff}_{\varepsilon } + 1\):

  29. (29)

    end do ## END of MAIN LOOP

  30. (30)

    #

  31. (31)

    ### BUILD and PRINT PARTIAL-TWUALITY POLYNOMIAL

  32. (32)

    \(\varvec{poly} {:=} 0\):    # initialize polynomial

  33. (33)

    for \(j{:=}0 {\varvec{ to }} N\) do

  34. (34)

          \(poly {:=} poly + coF[j]*z^j\): od:

  35. (35)

    print(poly) : 

  36. (36)

    endproc:

Fig. 5
figure 5

Reproduction of Fig. 4

Example 5.2

We reproduce the ribbon graph of Fig. 4. To calculate the Poincaré-dual polynomial to that ribbon graph, we supply to Algorithm 5.4, the partial-twuality polynomial algorithm, the input parameters:

$$\begin{aligned} N= & {} 3 \\ W= & {} (1\ 10\ 6\ 9\ 3\ 5) \\ TC= & {} *\end{aligned}$$

The procedure Algorithm 5.2 returns the extended monodromy:

$$\begin{aligned} r_0[1,2,3]= & {} (1\ 2)(3\ 4),\, (5\ 6)(7\ 8),\, (9\ 10)(11\ 12) \\ r_2 [1,2,3]= & {} (1\ 4)(2\ 3),\, (5\ 8)(6\ 7),\, (9\ 12)(10\ 11) \\ \lambda [1,2,3]= & {} (1\ 3)(2\ 4),\, (5\ 7)(6\ 8),\, (9\ 11)(10\ 12) \\ \rho= & {} (1\ 10\ 6\ 9\ 3\ 5)(2\ 12\ 7\ 11\ 4\ 8) \\ \phi= & {} (1\ 9\ 4\ 6\ 10\ 8)(2\ 11\ 3\ 7\ 12\ 5) \end{aligned}$$

We trace the values of the procedure variables j (node number), Gray(j) (its Gray code), \(A_j\) (the corresponding ribbon subset), \({\mathfrak {e}}(G^{A_j})\) (the Euler-genus for the corresponding partial dual), and the vector coeff (whose coordinates record the number of times that each Euler-genus occurs).

j

Gray(j)

\(A_j\)

\({\mathfrak {e}}(G^{A_j})\)

\(\hbox {coeff}[0,1,2,3]\)

0

0

\(\emptyset \)

3

 [0, 0, 0, 1]

1

1

\(\{1\}\)

1

[0, 1, 0, 1]

2

3

\(\{1,2\}\)

3

[0, 1, 0, 2]

3

2

\(\{2\}\)

2

[0, 1, 1, 2]

4

6

\(\{2,3\}\)

1

[0, 2, 1, 2]

5

7

\(\{1,2,3\}\)

3

[0, 2, 1, 3]

6

5

\(\{1,3\}\)

2

[0, 2, 2, 3]

7

4

\(\{3\}\)

3

[0, 2, 2, 4]

Accordingly, the graph of Fig. 4 has the Poincaré partial-duality polynomial

$$\begin{aligned} 2z + 2z^2 + 4z^3. \end{aligned}$$

Thus, like the polynomial (4.3) of [11], it is unimodal but not log-concave.