Request for Feedback: Invocation Tree – A Python Visualization Tool for Recursion

Hi everyone,

I’ve been working on invocation_tree, a Python package designed to visualize the Python call tree in real time. It’s main purpose is to help explain recursion, a concept beginners often struggle with. You can find my recursion explanation here. I hope the visualization gives an intuitive representation of the depth-first nature of recursion as the learner steps through his/her program, either in their favorite IDE, or in the Invocation Tree Web Debugger. See this live Quick Sort demo in the Web Debugger.

I’d love to hear your thoughts on its utility and any suggestions for improvement. If you have a moment to try it or share your perspective, I’d greatly appreciate it.

Thank you in advance for your feedback!

permutation_wd

4 Likes

This is pretty cool, @bterwijn ! I will definitely consider using this in teaching divide and conquer methods.

I ran your Web Debugger on the following code, and it worked perfectly.

def count_inversions(L):
    if len(L) <= 1:
        return L, 0
    L1, L2 = L[:len(L) // 2], L[len(L) // 2:]
    L1, inv1 = count_inversions(L1)
    L2, inv2 = count_inversions(L2)

    i1 = i2 = 0
    L_sorted = []
    inv = 0
    while i1 < len(L1) and i2 < len(L2):
        if L1[i1] < L2[i2]:
            L_sorted.append(L1[i1])
            i1 += 1
        else:
            inv += len(L1) - i1
            L_sorted.append(L2[i2])
            i2 += 1
    return L_sorted + L1[i1:] + L2[i2:], inv + inv1 + inv2

import random
lst = list(range(1,9))
random.shuffle(lst)
print(lst)
_, inversions = count_inversions(lst)
print("inversions:", inversions)

Would it be possible to get `monospace` font in the diagram?

Glad you liked it, I hope it brings much value for your teaching.

If you click “Config” it shows how you can set different fonts, this is your count_inversion with monospace Courier font.

Thanks!

Another question: would it be possible to (for example) annotate lines/statements/functions with a comment (similar to `# noqa`, perhaps) that your tool would then either collapse or hide altogether?

Example code:

import math
from collections import namedtuple as T
import itertools as IT

Point = T("Point", "x y")
Sol = T("Sol", "delta pair")

def bruteforce(points):
    return min(Sol(math.hypot(a.x - b.x, a.y - b.y), (a, b)) for (a, b) in IT.combinations(points, 2))

def closest_pair(X, Y):
    if len(X) <= 3:
        return bruteforce(X)
    pivot = len(X) // 2
    Xl = [p for (i, p) in enumerate(X) if i < pivot]
    L = set(Xl)  # expected O(1) lookup
    Xr = [p for p in X if p not in L]
    Yl = [p for p in Y if p in L]
    Yr = [p for p in Y if p not in L]
    OPT = min(closest_pair(Xl, Yl), closest_pair(Xr, Yr))
    line = X[pivot].x
    S = [p for p in Y if abs(p.x - line) < OPT.delta]
    if len(S) > 1:
        OPT = min(OPT, min(bruteforce(IT.islice(S[i:], 6)) for i in range(len(S) - 1)))
    return OPT

def closest(points):
    X = sorted(points)
    Y = sorted(points, key=lambda p: (p.y, p.x))
    return closest_pair(X, Y)

import random
N = 32
P = [Point(round(random.random() * 100, 2),round(random.random() * 100, 2)) for _ in range(N)]
delta, (p1, p2) = closest(P)
print("delta:", round(delta, 3))

In this code I first create (in this case) 32 random points, and they take up 32 boxes, then I sort them, which seems to be another bunch of boxes, before the actual code starts running. I would like to ignore everything until the actual recursive function is called.

I realize that this might be a big ask!

With:

ivt_tree.hide_calls.add(‘function-name’)
ivt_tree.ignore_calls.add(‘function-name’)

you can hide/ignore functions, see the “Config” and documentation.

In your example the debugger doesn’t step over list comprehension nicely. I thought I’d fixed that, but apparently there is still a problem that I’ve to look into. This will take some time as I’m busy now. I also have some future work in mind to make it scale better for larger programs, but for now this is what it is. Half way 2026 I should have time for further development.

2 Likes