6
$\begingroup$

We are interested in a class of walks on the complete graph on $[n] = \{1,2,\dots,n\}$. A walk of length $k$ is an ordered tuple of directed edges $$ ((i_1,i_2),(i_2,i_3),\ldots,(i_k,i_{k+1})) $$ where $i_j \in [n]$ with $i_j \neq i_{j+1}$ for all $j$ (that is, the complete graph has no self-loops). We also write $i_1 \to i_2 \to i_3 \to \cdots \to i_k \to i_{k+1}$ to represent such a walk.

Consider closed walks that start and end on a specific node: Without loss of generality assume $i_1 = i_{k+1} = n$. We are interested in the subset of these walks with the following properties:

  • Have $t$ unique undirected edges (that is, we consider $1 \to 2$ and $2 \to 1$ as the same edge) ignoring multiplicity (that is, $1 \to 2 \to 1 \to 2 \to 1$ , has 1 unique edge).

  • The undirected graph generated by the walk is a tree (i.e., is connected and has no cycles). The undirected graph is obtained by ignoring the direction of edges and their multiplicity.

Examples with $n = 7, k = 6$ and $t=2$:

  • $7 \to 6 \to 7 \to 1 \to 7 \to 1 \to 7$: The undirected graph is: $1 - 7 - 6$
  • $7 \to 6 \to 1 \to 6 \to 7 \to 6 \to 7$: The undirected graph is: $7 - 6- 1$
  • $7 \to 1 \to 2 \to 1 \to 2 \to 1 \to 7$: The undirected graph is: $7-1-2$

The question is how many of these walks there are? Let's call this number $C_{k,t}^n$ and note that it is zero unless $k \in 2 \mathbb N$ and $t \le k/2$. So we can assume $k$ and $t$ satisfy these conditions.

The growth of $C_{k,t}^n$ in $n$ is like $n^t$ and we are mostly interested in the prefactor and how it grows in $(k,t)$. A sharp upper bound capturing the correct growth would be great.

PS. For example, $C_{6,2}^n = 6 (n-1) (n-2)$ which can be obtained by partitioning the walks based on how many times they return to $n$ (and so there seems to be some connection to partition of the integer $k/2$.) Also, the following lower bound seems to hold $C_{k,k/2}^n \ge 2^{k/2-1} (n-1)(n-2)\cdots(n-k/2)$

$\endgroup$
7
  • $\begingroup$ My intuition is that the growth in $k$, for $n$ and $t$ fixed, should be dominated by stars. So it should be something like $\sim {n-1\choose t}t^{\frac k2}+(n-1){n-2\choose t-1}t^{\frac k2-1}$ (depending if the hub is the starting vertex or not). $\endgroup$
    – Corentin B
    Commented Jul 13 at 20:01
  • $\begingroup$ This should follow from Theorem 1.1 in sciencedirect.com/science/article/pii/S0012365X04001475 $\endgroup$
    – Corentin B
    Commented Jul 13 at 20:06
  • 1
    $\begingroup$ It should still be $k\in 2\mathbb N$ (also, it should be $i_3$ in the definition of walk). I cannot find 6 more typos to make it a large enough edit though $\endgroup$
    – Corentin B
    Commented Jul 13 at 20:29
  • 1
    $\begingroup$ I'll write that as an answer $\endgroup$
    – Corentin B
    Commented Jul 13 at 20:29
  • 1
    $\begingroup$ I believe that we have $$C^n_{2t,t}=D_t\cdot (n−1)(n−2)…(n−t),$$ where $D_t=\frac1{t+1}{2t\choose t}$ is the number of Dyck paths of length $t$, commonly called the $t$-th Catalan number. The bijection is explicit: the Dyck path controls the distance from the starting point at any given time. Each time we go up in the Dyck path (this happens exactly $t$ times), we choose a vertex not yet visited to go to in the complete graph. Each time we go down, we come back on our steps. $\endgroup$
    – Corentin B
    Commented Jul 13 at 22:00

2 Answers 2

5
$\begingroup$

Let's fix $n$ as suggested. As $t\in\{1,2,\ldots,n\}$ a fixed finite set, let's fix $t$ too. For a tree $T\ni n$, we denote $c_{\subseteq T}(\ell)$ the number of closed walks of length $2\ell$ in $T$, and $c_T(\ell)$ the number of walks that moreover visit all vertices of $T$.

The number $c_{\subseteq T}(\ell)$ is an entry of $A_T^{2\ell}$, where $A_T$ is the adjacency matrix of $T$. As $T$ is connected, Perron-Frobenius tells us the largest eigenvalue $\lambda_T$ has multiplicity one, and $$ c_{\subseteq T}(\ell) \sim a_T\cdot \lambda_T^{2\ell}.$$ (We have to be careful about periodicity issues: $A_T$ has period $2$ as $T$ is bipartite so there is another eigenvalue of maximal modulus, namely $-\lambda_T$. This is why we look at even powers.)

Moreover, except for an exponentially small subset (controlled by walks in proper subtrees, with smaller $\lambda$), these walks cover all of $T$. Therefore, $c_{T}(\ell)\sim c_{\subseteq T}(\ell)\sim a_T\cdot \lambda_T^{2\ell}$ too.

We have $$ C^n_{2\ell,t} = \sum_{|ET|=t, T\ni n} c_{T}(\ell) \sim \sum_{|ET|=t, T\ni n}c_{\subseteq T}(\ell) \sim b\cdot \max\{\lambda_T:|ET|=t \}^{2\ell}.$$ By Theorem 4.7 of The second largest eigenvalue of a tree of Neumaier, the (first) largest eigenvalue of a tree $T$ satisfies $\lambda_T\le \sqrt t$, with equality if and only if $T$ is a star. So we only have to compute $c_{\subseteq T}(\ell)$ for $T$ a star to get the asymptotic of $C^n_{2\ell,t}$, as the other terms are exponentially negligable.

  • If $T$ is a star with $n$ the hub, we have $c_{\subseteq T}(\ell)=t^\ell$. There are ${n-1\choose t}$ such trees.
  • If $T$ is a star with $n$ a leaf, we have $c_{\subseteq T}(\ell)=t^{\ell-1}$. There are $(n-1){n-2\choose t-1}$ such trees.

We conclude that $$ C^n_{2\ell,t} \sim \left({n-1\choose t}+\frac{n-1}{t}{n-2\choose t-1}\right) \cdot t^{\ell} = 2{n-1\choose t}\cdot t^\ell, $$ as $\ell\to\infty$, and the error term is exponentially small.

N.B. Here $f\sim g$ means the quotient $f/g$ goes to $1$.

$\endgroup$
2
  • $\begingroup$ Very interesting, although I can't say I follow all the steps. This pretty much answers it. But I was wondering if this type of argument can be made into a hard inequality that always holds (say by inflating that final 2 to a larger constant)? $\endgroup$
    – passerby51
    Commented Jul 13 at 22:38
  • $\begingroup$ I think I have an upper bound based on your comments. If only we can prove that the counts of walks on the star is always the maximum (not just asymptotically). $\endgroup$
    – passerby51
    Commented Jul 14 at 2:20
0
$\begingroup$

Based on the answer and comments by @Corentin B, I believe the following upper bound holds: $$ C_{k,t}^n \leq D_t \binom{n-1}{t}\cdot t! \cdot S(k/2,t) $$ for $k \in 2 \mathbb N$ and $t \le k/2$, where $D_t = \frac1{t+1}\binom{2t}{t}$ is the Catalan number and $S(\cdot, \cdot)$ the Stirling number of the second kind.

The bound is tight when $k = 2t$.

Here is a tentative proof:


There are $C_t$ (plane) tree structures (when we try to encode the structure of the walk starting from the left we get one of these plane trees) and the count of walks for each structure is upper-bounded by the count for the star (*) Once we pick the leaves of the star, for which we have $\binom{n-1}{t}$ choices, then we have to choose how many times we want to visit each leaf and in what order, making sure we visit each leaf at least once.

The latter count is $t! \cdot S(k/2,t)$. To see this note that walks of the kind we want on a star with $n$ in the center, is equivalent to arranging $t$ objects into $m=k/2$ slots where (a) each object must be used at least once (to cover the tree), (b) objects can be used multiple times and (c) the order matters. This is equivalent to the number of surjections from a set of $m$ elements to a set of $t$ elements which is given by $ t! \cdot S(m,t)$.


The only really missing piece is formally proving the upper bound (*) which seems to be true.


The output of a bit of code that inspired this: The above upper bound is obtained by assuming all the $D_4$ = 14 counts are 1560.

Enter the number of nodes (n): 5
Enter the path length (k): 12
Enter the number of unique undirected edges (t): 4

Loopless paths grouped by tree structure:
Tree structure: (((),(),()))
  Number of paths: 1560
  Example path: 5 -> 1 -> 2 -> 1 -> 2 -> 1 -> 2 -> 1 -> 3 -> 1 -> 4 -> 1 -> 5

Tree structure: ((),(),(),())
  Number of paths: 1560
  Example path: 5 -> 1 -> 5 -> 1 -> 5 -> 1 -> 5 -> 2 -> 5 -> 3 -> 5 -> 4 -> 5

Tree structure: ((()),(),())
  Number of paths: 1264
  Example path: 5 -> 1 -> 2 -> 1 -> 2 -> 1 -> 2 -> 1 -> 5 -> 3 -> 5 -> 4 -> 5

Tree structure: ((),(()),())
  Number of paths: 1264
  Example path: 5 -> 1 -> 5 -> 1 -> 5 -> 1 -> 5 -> 2 -> 3 -> 2 -> 5 -> 4 -> 5

Tree structure: ((),(),(()))
  Number of paths: 1264
  Example path: 5 -> 1 -> 5 -> 1 -> 5 -> 1 -> 5 -> 2 -> 5 -> 3 -> 4 -> 3 -> 5

Tree structure: (((),()),())
  Number of paths: 1260
  Example path: 5 -> 1 -> 2 -> 1 -> 2 -> 1 -> 2 -> 1 -> 3 -> 1 -> 5 -> 4 -> 5

Tree structure: ((),((),()))
  Number of paths: 1260
  Example path: 5 -> 1 -> 5 -> 1 -> 5 -> 1 -> 5 -> 2 -> 3 -> 2 -> 4 -> 2 -> 5

Tree structure: (((),(())))
  Number of paths: 1152
  Example path: 5 -> 1 -> 2 -> 1 -> 2 -> 1 -> 2 -> 1 -> 3 -> 4 -> 3 -> 1 -> 5

Tree structure: (((()),()))
  Number of paths: 1152
  Example path: 5 -> 1 -> 2 -> 1 -> 2 -> 1 -> 2 -> 3 -> 2 -> 1 -> 4 -> 1 -> 5

Tree structure: ((((),())))
  Number of paths: 1032
  Example path: 5 -> 1 -> 2 -> 1 -> 2 -> 1 -> 2 -> 3 -> 2 -> 4 -> 2 -> 1 -> 5

Tree structure: ((()),(()))
  Number of paths: 1008
  Example path: 5 -> 1 -> 2 -> 1 -> 2 -> 1 -> 2 -> 1 -> 5 -> 3 -> 4 -> 3 -> 5

Tree structure: (((())),())
  Number of paths: 900
  Example path: 5 -> 1 -> 2 -> 1 -> 2 -> 1 -> 2 -> 3 -> 2 -> 1 -> 5 -> 4 -> 5

Tree structure: ((),((())))
  Number of paths: 900
  Example path: 5 -> 1 -> 5 -> 1 -> 5 -> 1 -> 5 -> 2 -> 3 -> 4 -> 3 -> 2 -> 5

Tree structure: ((((()))))
  Number of paths: 792
  Example path: 5 -> 1 -> 2 -> 1 -> 2 -> 1 -> 2 -> 3 -> 4 -> 3 -> 2 -> 1 -> 5

Total loopless paths: 16368

Unique tree structures: 14
Our guess (Catalan number D_4): 14

Actual largest count:   1560 (for structure: (((),(),())))
Our guess:              1560 (comb(n-1, t) * factorial(t) * stirling2(k//2, t))

Star structure count: 1560
Is star structure the one with largest count? Yes

Upper bound on total count: 21,840
Actual total count:         16,368
Is the calculated upper bound valid? Yes

The tree structure is represented as nested parentheses, where each set of parentheses represents a node and its children. We sort the children before creating the representation. Let's call this the Cayley structure of the tree.


So why not Cayley's formula $(t+1)^{t-1}$ rather than the Catalan number? Consider $n=4$ and $t=3$, then Cayley's formula counts 3 different stars with $n=4$ as a leaf, let's call them $T_1,T_2$ and $T_3$, while Catalan's counts just 1, i.e. ((()())). Both formulas count a single star with $n=4$ as the hub, i.e., ((),(),()).

The count $\binom{n-1}{t} t! S(k/2,t)$ correctly gives the count of walks on the hub-star ((),(),()). For any of these walks, if we switch the hub with one of the leaves, we get a corresponding walk on either $T_1, T_2$ or $T_3$ (**). So the totality of walks on $T_1,T_2$ and $T_3$ is in 1-1 correspondence with walks on ((),(),()). That is, all possible walks on ((),(),()) are in 1-1 correspondence with all possible walks on ((()())).

This suggest that we partition the walks based on their Cayley structure, and assuming the above two star Cayley structures are maximal, we get a better bound.

(**) How the 1-1 correspondence work? Consider $$4 \to 1 \to 2 \to 1 \to 3 \to 1 \to 4$$ We glue the two ends together and start the walk on the second node, 1, and continue for $k = 6$ steps to get $$1 \to 2 \to 1 \to 3 \to 1 \to 4 \to 1$$ Now this is a walk on a ((),(),()) with hub node $1$. We just flip $1$ and $4$: $$4 \to 2 \to 4 \to 3 \to 4 \to 1 \to 4$$ which gives our desired walk on ((),(),()) with 4 at the center.


Here is the code

from typing import List, Tuple, Set
from collections import defaultdict
from math import comb, factorial

def catalan(n):
    return comb(2*n, n) // (n + 1)

def stirling2(n, k):
    if n == k == 0:
        return 1
    if n == 0 or k == 0:
        return 0
    return stirling2(n-1, k-1) + k * stirling2(n-1, k)

def generate_paths(n: int, k: int, t: int) -> List[Tuple[List[int], int, str]]:
    paths_without_loops = []
    
    def has_loop(edges: Set[Tuple[int, int]]) -> bool:
        graph = defaultdict(set)
        for u, v in edges:
            graph[u].add(v)
            graph[v].add(u)
        
        def dfs(node: int, parent: int) -> bool:
            visited[node] = True
            for neighbor in graph[node]:
                if not visited[neighbor]:
                    if dfs(neighbor, node):
                        return True
                elif neighbor != parent:
                    return True
            return False
        
        visited = [False] * (n + 1)
        for node in range(1, n + 1):
            if not visited[node]:
                if dfs(node, -1):
                    return True
        return False

    def get_tree_structure(path: List[int]) -> str:
        edges = set()
        for i in range(len(path) - 1):
            u, v = path[i], path[i+1]
            edges.add((min(u, v), max(u, v)))
        
        graph = defaultdict(set)
        for u, v in edges:
            graph[u].add(v)
            graph[v].add(u)
        
        def dfs_structure(node: int, parent: int) -> str:
            children = sorted(neighbor for neighbor in graph[node] if neighbor != parent)
            return f"({','.join(dfs_structure(child, node) for child in children)})"
        
        root = path[0]
        return dfs_structure(root, -1)

    def backtrack(path: List[int], unique_edges: Set[Tuple[int, int]], returns: int):
        if len(path) == k + 1:
            if path[-1] == n and len(unique_edges) == t:
                if not has_loop(unique_edges):
                    tree_structure = get_tree_structure(path)
                    paths_without_loops.append((path[:], returns, tree_structure))
            return
        
        for next_node in range(1, n + 1):
            if next_node != path[-1]:
                new_edge = (min(path[-1], next_node), max(path[-1], next_node))
                new_unique_edges = unique_edges.copy()
                new_unique_edges.add(new_edge)
                if len(new_unique_edges) <= t:
                    new_returns = returns + (1 if next_node == n else 0)
                    path.append(next_node)
                    backtrack(path, new_unique_edges, new_returns)
                    path.pop()

    backtrack([n], set(), 0)
    return paths_without_loops

def display_paths(paths: List[Tuple[List[int], int, str]]):
    print("\nLoopless paths grouped by tree structure:")
    total_paths = 0
    tree_structure_counts = defaultdict(int)
    
    for path, returns, tree_structure in paths:
        tree_structure_counts[tree_structure] += 1
        total_paths += 1
    
    for structure, count in sorted(tree_structure_counts.items(), key=lambda x: x[1], reverse=True):
        print(f"Tree structure: {structure}")
        print(f"  Number of paths: {count}")
        print(f"  Example path: {' -> '.join(map(str, next(path for path, _, s in paths if s == structure)))}")
        print()
    
    print(f"Total loopless paths: {total_paths}")
    print(f"Unique tree structures: {len(tree_structure_counts)}")

def display_paths(paths: List[Tuple[List[int], int, str]], n: int, k: int, t: int):
    print("\nLoopless paths grouped by tree structure:")
    total_paths = 0
    tree_structure_counts = defaultdict(int)
    
    for path, returns, tree_structure in paths:
        tree_structure_counts[tree_structure] += 1
        total_paths += 1
    
    max_count = 0
    max_structure = ""
    star_structure = "(" + ",".join(["()" for _ in range(t)]) + ")"
    star_count = 0
    
    for structure, count in sorted(tree_structure_counts.items(), key=lambda x: x[1], reverse=True):
        print(f"Tree structure: {structure}")
        print(f"  Number of paths: {count}")
        print(f"  Example path: {' -> '.join(map(str, next(path for path, _, s in paths if s == structure)))}")
        print()
        
        if count > max_count:
            max_count = count
            max_structure = structure
        
        if structure == star_structure:
            star_count = count
    
    print(f"Total loopless paths: {total_paths}")
    print(f"\nUnique tree structures: {len(tree_structure_counts)}")
    
    # Catalan number estimate
    catalan_estimate = catalan(t)
    print(f"Our guess (Catalan number D_{t}): {catalan_estimate}")
    #print(f"Actual number of unique tree structures: {len(tree_structure_counts)}")
    
    # Exact count for the tree structure with largest walks
    guess_max_count = comb(n-1, t) * factorial(t) * stirling2(k//2, t)
    print(f"\nActual largest count: {max_count:6d} (for structure: {max_structure})")
    print(f"Our guess:            {guess_max_count:6d} (comb(n-1, t) * factorial(t) * stirling2(k//2, t))")
    
    # Star structure count
    print(f"\nStar structure count: {star_count}")
    print(f"Is star structure the one with largest count? {'Yes' if star_count == max_count else 'No'}")
    
    # Upper bound calculation
    upper_bound = catalan_estimate * guess_max_count
    print(f"\nUpper bound on total count: {upper_bound:6,d}")
    print(f"Actual total count:         {total_paths:6,d}")
    print(f"Is the calculated upper bound valid? {'Yes' if upper_bound >= total_paths else 'No'}")

def main():
    n = int(input("Enter the number of nodes (n): "))
    k = int(input("Enter the path length (k): "))
    t = int(input("Enter the number of unique undirected edges (t): "))

    paths_without_loops = generate_paths(n, k, t)
    display_paths(paths_without_loops, n, k, t)

if __name__ == "__main__":
    main()
$\endgroup$
8
  • $\begingroup$ Here is a small observation in the direction of (*). Super-multiplicativity of $c_{\subseteq T}$ and Fekete’s lemma tells us $$\lambda_T=\limsup_{\ell\to\infty}c_{\subseteq T}(\ell)^{\frac1{2\ell}}\overset!= \sup_{\ell\ge 1}c_{\subseteq T}(\ell)^{\frac1{2\ell}},$$ hence $$c_T(\ell)\le c_{\subseteq T}(\ell)\le \lambda_T^{2\ell}\le t^\ell.$$ (Note that $S(\ell,t)\sim t^\ell$ as $\ell\to\infty$.) $\endgroup$
    – Corentin B
    Commented Jul 14 at 8:27
  • $\begingroup$ I don’t understand why the leading term is $D_t {n-1\choose t}$ here. Shouldn’t it be $(t+1)^{t-1}{n-1\choose t}$, using Cayley’s formula for labeled trees? $\endgroup$
    – Corentin B
    Commented Jul 14 at 8:32
  • $\begingroup$ Correction: $t! S(\ell,t)\sim t^\ell$. $\endgroup$
    – Corentin B
    Commented Jul 14 at 9:32
  • 1
    $\begingroup$ Thanks @CorentinB. I am a bit confused myself as to why not Cayley's, but I have updated the post with an argument ... It seems that if we partition it this way (with Cayley structure), we get a better bound (otherwise, that $\binom{n-1}{t} t! S(k/2,t)$ will be bounding walks on what I called $T_2, T_3$ and $T_4$ separately, as opposed to bounding their total walks. $\endgroup$
    – passerby51
    Commented Jul 14 at 19:43
  • $\begingroup$ Also included the code at the end. $\endgroup$
    – passerby51
    Commented Jul 14 at 19:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .