Visual study of the winding number of a closed path in the complex plane. The Argument Principle

This notebook is dedicated to the so called Argument Principle for meromorphic functions. More precisely we visualize the geometric version of this principle, which allows to identify zeros and singularities in a graphical representation of a complex valued function by domain coloring method.

The Argument Principle relates the number of zeros and singularities of a function with the so called winding number of a loop encircling these points.

We present the winding number both theoretically and visually (animated).

Winding number of a closed loop with respect to a point

A closed path or loop in the complex plane is defined by a continuous function $\gamma:[a,b]\to\mathbb{C}$, such that $\gamma(a)=\gamma(b)$. The range or image of the function $\gamma$ is a curve $\Gamma=im(\gamma)$ in the complex plane.

The path can be interpreted as defining the motion of a point on the curve $\Gamma$, during the interval of time $[a,b]$.

For example $\gamma(t)=z_0+re^{2\pi i t}$, $t\in[0,1]$, defines a loop. The moving point describes a circle centered at $z_0$ and of radius $r$.

A loop $\gamma:[a,b]\to\mathbb{C}$ which has no selfintersections, except for $\gamma(a)=\gamma(b)$, is called simple loop.

$\gamma(t)=z_0+re^{2\pi i t}$ defines a simple loop for $t\in[0,1]$, while the loop defining the figure eight by: $\gamma(t)=\cos(t)+i \sin(t)\cos(t)$, $t \in [-\pi/2, 3\pi/2]$ is not simple.

A simple loop $\gamma$ divides the complex plane into two regions, whose common boundary is the curve $\Gamma=im(\gamma)$. The bounded region is usually called the region inside $\Gamma$.

Let $z_0$ be a point in the complex plane and $\gamma:[a,b]\to\mathbb{C}\setminus\{z_0\}$ a loop not passing through $z_0$. The winding number of $\gamma$ with respect to $z_0$ is, intuitively, the number of times the moving point $\gamma(t)$ winds around $z_0$, as $t$ varies in $[a,b]$. We denote this number by $wind(\gamma, z_0)$.

In order to give a formal definition of the winding number we consider first loops that avoid 0, and are defined (eventually through a reparameterization) on the interval $[0,1]$.

If $\gamma:[0,1]\to\mathbb{C}\setminus \{0\}$ is a loop, then there exists a continuous path $\eta:[0,1]\to\mathbb{C}$, such that $$\gamma(t)=e^{\eta(t)}=r(t)e^{i \varphi(t)}, \quad\forall\: t\in [0,1]$$

The real functions $r(t)$ and $\varphi(t)$ are obviously continuous, and they are uniquely defined up to multiples of $2\pi$.

The real function $\varphi(t)$ unwraps the argument of $\gamma(t)$. In Complex Analysis it is called a continuous branch of the argument along $\gamma(t)$, whereas in Topology the function $\varphi/2\pi$ is a lift of the path $t\mapsto \displaystyle\frac{\gamma(t)}{|\gamma(t)|}$ in the unit circle $\mathbb{S}^1=\mathbb{R}/\mathbb{Z}$, to a path in $\mathbb{R}$.

Since $\gamma$ is a loop we have $\gamma(0)=\gamma(1)$ $\Leftrightarrow$ $r(0)e^{i\varphi(0)}=r(1)e^{i\varphi(1)}$ $\Leftrightarrow$ $r(0)=r(1)$ and $\varphi(1)-\varphi(0)=2 k\pi$, for some integer $k$.

By the definition given for example in P. Henrici, Applied and computational complex analysis, Vol 1,, the integer $k$ is the winding number of the loop with respect to $0$, $k=wind(\gamma,0)$.

It gives the total continuous variation of the angle along the loop.

If a loop $\gamma$ avoids a point $z_0$, then the loop $\xi$, $\xi(t)=\gamma(t)-z_0$, avoids $0$, and thus one defines the winding number of the loop $\gamma$ with respect to $z_0$ as being $wind(\gamma, z_0)=wind(\xi, 0)$.

  • The winding number is positive when the path $\gamma$ is positively oriented ($\gamma(t)$ moves anticlockwise on the underlying curve $\Gamma$, as $t$ increases from $a$ to $b$).
  • It is negative when $\gamma$ is negatively oriented, and $0$ when $z_0$ is "outside" the curve $\Gamma$.

In order to get more insight into this notion, we take a loop and animate the motion of the vector $\overrightarrow{z_0\gamma(t)}$ about $z_0$, as $\gamma(t)$ is running along the curve $\Gamma$, from its starting point $\gamma(0)$, and back.

To activate and display the animation within the IPython Notebook we call the function matplotlib.animation and import the package JSAnimation (it can be installed via pip).

In [1]:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import animation
from JSAnimation import IPython_display
In [2]:
def moving_vector(gammat, z0, xm, xM, ym, yM):
    # gammat is an array of N complex numbers, representing the values of gamma(t) at 
    # t=np.linspace(0,1, N)
    #xm, xM, ym, yM are  axes limits 
    
    nr = gammat.real.shape[0]
    
    def init():
        v = ax.quiver([], [], [], [], color=(0.45,0.45, 0.45), scale_units='xy', angles='xy',
                scale=1, linewidth=.1)
        return v,
            
    def animate(i):
        v.set_UVC(gammat[i].real, gammat[i].imag)
        return   v,

    fig = plt.figure()
    ax = fig.add_subplot(111, xlim=(xm, xM), ylim=(xm, xM))
    ax.grid()
    ax.plot(gammat.real, gammat.imag, 'g', lw=2)
    ax.plot(gammat[0].real, gammat[0].imag, 'ro') #the starting point  
    ax.plot(z0.real, z0.imag, color=(0.45, 0.45, 0.45), marker='o')     
    X = []
    Y = []
    X.append(z0.real)
    Y.append(z0.imag) 
    v = ax.quiver( X, Y, [], [], color=(0.45,0.45, 0.45), scale_units='xy', angles='xy',
            scale=1, linewidth=.1)
    anim = animation.FuncAnimation(fig, animate, init_func=init, frames=nr, blit=True,
                                  interval=30, repeat=False)
    return anim  

To start the animation, one clicks the right black triangle. To restart it, click the left black triangle and wait until the slider reaches the left end, and then click the right triangle again.

Example: we read from a file the real and imaginary parts of the values $\gamma(t)$, where $t$ is the array t=np.linspace(0,1, N):

In [3]:
data = np.loadtxt('Gamma.txt')
gamma = data[:, 0]+1j*data[:, 1]
anim = moving_vector(gamma, 0.0, -6,6, -4,6)
IPython_display.display_animation(anim, default_mode='once')  
Out[3]:


Once Loop Reflect