Monday, 6 April 2026

How many roots of f(z) = i*z^15 + z*sin(z) + z^3*exp(2*z) are in the right half-plane and how many are in the left ?

 Follow code proposed in https://lxer.com/module/newswire/view/363645/index.html . Setup python3.14.3t on CachyOS along with aqtinstall via UV

   $ curl -LsSf https://astral.sh/uv/install.sh | sh
   $ uv python install 3.14t                                                                              $ uv python list
   $ mkdir MULTITHREAD
   $ cd MULTITHREAD
   $ python3.14t -m venv .env
   $ source .env/bin/activate
   $ pip install aqtinstall
   $ pip install --upgrade pip
   $ pip install numpy matplotlib cxroots

  

cat complexSinZExpZ05.py
import os
import numpy as np
import matplotlib.pyplot as plt
from cxroots import Circle
from concurrent.futures import ThreadPoolExecutor

# Silence Qt warnings
os.environ["QT_LOGGING_RULES"] = "*.debug=false;qt.qpa.fonts.warning=false"

def count_zeros_task(f, df, contour_points):
"""Calculates zeros via the Argument Principle."""
fz, dfz = f(contour_points), df(contour_points)
integrand = dfz / fz
dz = np.diff(contour_points, append=contour_points[0])
integral = np.sum(integrand * dz)
return int(np.round((integral / (2j * np.pi)).real))

def find_roots_task(contour, f, df):
"""Calculates specific root locations using cxroots."""
return contour.roots(f, df)

# 1. Setup Data
f = lambda z: 1j*z**15 + z*np.sin(z) + z**3*np.exp(2*z)  
df = lambda z: 15j*z**14 + z*np.cos(z) + np.sin(z) +  3*z**2*np.exp(2*z) + 2*z**3*np.exp(2*z)

t = np.linspace(0, 2 * np.pi, 10000)
circle_pts = 5*np.exp(1j * t)
C = Circle(0, 5)

print("f(z) = 1j*z**15 + z*np.sin(z) + z**3*np.exp(2*z)")
print("Starting concurrent calculations...")

# 2. Parallel Execution
with ThreadPoolExecutor() as executor:
# Submit both tasks to run simultaneously
future_count = executor.submit(count_zeros_task, f, df, circle_pts)
future_roots = executor.submit(find_roots_task, C, f, df)

# Retrieve results (this waits for each to finish)
zero_count = future_count.result()
roots_result = future_roots.result()


# 3. Output and Visualization
print(f"\nVerification (Argument Principle): {zero_count} zeros found.")
print(f"Detailed Root Analysis:\n{roots_result}")

# Plotting must happen on the main thread
roots_result.show()
plt.show()



Add to the bottom of ~/.bashrc                                                        function activatevenv() {
 # Names of possible virtualenv directories
 VIRTUALENV_DIRS=("venv/" "env/" ".env/" ".venv/" "${PWD##*/}")

 for dir in "${VIRTUALENV_DIRS[@]}"; do
   if [[ -d "${dir}" ]]; then
     # Found a possible venv directory
     # Try activating the venv
     if [[ -e "./${dir}/bin/activate" ]]; then
       source ./$dir/bin/activate
       echo "Virtual environment activated automatically"
       break
     fi
   fi
 done

}
# Extension for `cd` command in order to automatically activate virtual env when changing directories.
cd() {
 builtin cd $1
 # Try activating venv
 activatevenv
}

Saturday, 4 April 2026

How many roots of polynomials provided in this post are in the right half-plane and how many are in the left ?

Follow code proposed in https://lxer.com/module/newswire/view/363645/index.html . Setup python3.14.3t on CachyOS along with aqtinstall via UV

   $ curl -LsSf https://astral.sh/uv/install.sh | sh
   $ uv python install 3.14t 
                                                                             $ uv python list
   $ mkdir MULTITHREAD
   $ cd MULTITHREAD
   $ python3.14t -m venv .env
   $ source .env/bin/activate
   $ pip install aqtinstall
   $ pip install --upgrade pip
   $ pip install numpy matplotlib cxroots
 


cat complexThreaded12.py
import os
import numpy as np
import matplotlib.pyplot as plt
from cxroots import Circle
from concurrent.futures import ThreadPoolExecutor

# Silence Qt warnings
os.environ["QT_LOGGING_RULES"] = "*.debug=false;qt.qpa.fonts.warning=false"

def count_zeros_task(f, df, contour_points):
 """Calculates zeros via the Argument Principle."""
 fz, dfz = f(contour_points), df(contour_points)
 integrand = dfz / fz
 dz = np.diff(contour_points, append=contour_points[0])
 integral = np.sum(integrand * dz)
 return int(np.round((integral / (2j * np.pi)).real))

def find_roots_task(contour, f, df):
 """Calculates specific root locations using cxroots."""
 return contour.roots(f, df)

# 1. Setup Data
f = lambda z: 3*z**12 + 5*z**10 + 3*z**7 + z**5 + z**4 + 4*z**3 + 10*z**2 + 9  
df = lambda z: 36*z**11 +  50*z**9 + 21*z**6 +  5*z**4 + 4*z**3 + 12*z**2 + 20*z

t = np.linspace(0, 2 * np.pi, 1000)
circle_pts = 3 * np.exp(1j * t)
C = Circle(0, 3)

print("Starting concurrent calculations...")

# 2. Parallel Execution
with ThreadPoolExecutor() as executor:
 # Submit both tasks to run simultaneously
 future_count = executor.submit(count_zeros_task, f, df, circle_pts)
 future_roots = executor.submit(find_roots_task, C, f, df)

 # Retrieve results (this waits for each to finish)
 zero_count = future_count.result()
 roots_result = future_roots.result()


# 3. Output and Visualization
print(f"\nVerification (Argument Principle): {zero_count} zeros found.")
print(f"Detailed Root Analysis:\n{roots_result}")

# Plotting must happen on the main thread
roots_result.show()
plt.show()

 

Another test for z**15 + 8*z**5 + 7*z + 9

cat  complexThreaded15.py
import os
import numpy as np
import matplotlib.pyplot as plt
from cxroots import Circle
from concurrent.futures import ThreadPoolExecutor

# Silence Qt warnings
os.environ["QT_LOGGING_RULES"] = "*.debug=false;qt.qpa.fonts.warning=false"

def count_zeros_task(f, df, contour_points):
"""Calculates zeros via the Argument Principle."""
fz, dfz = f(contour_points), df(contour_points)
integrand = dfz / fz
dz = np.diff(contour_points, append=contour_points[0])
integral = np.sum(integrand * dz)
return int(np.round((integral / (2j * np.pi)).real))

def find_roots_task(contour, f, df):
"""Calculates specific root locations using cxroots."""
return contour.roots(f, df)

# 1. Setup Data
f = lambda z: z**15 + 8*z**5 + 7*z + 9   
df = lambda z: 15*z**14 + 40*z**4 + 7


t = np.linspace(0, 2 * np.pi, 1000)
circle_pts = 5 * np.exp(1j * t)
C = Circle(0, 5)

print("For polynom z**15 + 8*z**5 + 7*z + 9")
print("Starting concurrent calculations...")

# 2. Parallel Execution
with ThreadPoolExecutor() as executor:
# Submit both tasks to run simultaneously
future_count = executor.submit(count_zeros_task, f, df, circle_pts)
future_roots = executor.submit(find_roots_task, C, f, df)

# Retrieve results (this waits for each to finish)
zero_count = future_count.result()
roots_result = future_roots.result()


# 3. Output and Visualization
print(f"\nVerification (Argument Principle): {zero_count} zeros found.")
print(f"Detailed Root Analysis:\n{roots_result}")

# Plotting must happen on the main thread
roots_result.show()
plt.show()



Add to the bottom of ~/.bashrc                                                        function activatevenv() {
 # Names of possible virtualenv directories
 VIRTUALENV_DIRS=("venv/" "env/" ".env/" ".venv/" "${PWD##*/}")

 for dir in "${VIRTUALENV_DIRS[@]}"; do
   if [[ -d "${dir}" ]]; then
     # Found a possible venv directory
     # Try activating the venv
     if [[ -e "./${dir}/bin/activate" ]]; then
       source ./$dir/bin/activate
       echo "Virtual environment activated automatically"
       break
     fi
   fi
 done

}
# Extension for `cd` command in order to automatically activate virtual env when changing directories.
cd() {
 builtin cd $1
 # Try activating venv
 activatevenv
}

REFERENCES

https://gist.github.com/kishannareshpal/342efc4a15e47ea5d338784d3e9a8d98 

 

Setup python3.14.3t on Fedora 44 Server along with aqtinstall via UV

Just follow same schema as in previous blog entry 

   =======================================
   $ sudo dnf install @development-tools
   $ sudo dnf install python3-pip
  =======================================
   $ curl -LsSf https://astral.sh/uv/install.sh | sh
   $ uv python install 3.14t 
                                                                             $ uv python list
   $ mkdir MULTITHREAD
   $ cd MULTITHREAD
   $ python3.14t -m venv .env
   $ source .env/bin/activate
   $ pip install aqtinstall
   $ pip install --upgrade pip
   $ pip install numpy matplotlib cxroots



Wednesday, 1 April 2026

Setup python3.14.3t on Debian Trixie/Forky along with aqtinstall via pyenv

UPDATE as of 04/06/2026

  How many roots of f(z) = i*z^15 + z*sin(z) + z^3*exp(2*z) are in the right half-plane and how many are in the left ?

END UPDATE 

 Command-line utility "aqtinstall" enables plotting in Python 3.14.3t by automating the installation of Qt binaries (e.g., PyQt6 ) , which are required by libraries like Matplotlib to render interactive graphs. It serves as a command-line alternative to the official Qt installer, facilitating the setup of necessary GUI frameworks, often in CI environments or specific Python versions. Dependency Management: It resolves and installs the required Qt components, allowing pip install matplotlib to function correctly for creating interactive plots. Version Compatibility: It can install specific, prebuilt Qt binaries compatible with the latest Python versions, such as 3.14, by targeting the required OS and compiler. Integration: The installed Qt libraries allow Matplotlib plots to be embedded directly into GUI applications, providing interactive, zoomable, and pannable figures.

 
Setup pyenv on Debian Trixie/Forky
$ sudo apt update
$ sudo apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev git gcc

$ curl -fsSL https://pyenv.run | bash
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc
$ source 
~/.bashrc
 
List versions: pyenv install --list
$  pyenv install 3.14.3t
Set global version
$ pyenv global 3.14.3t

For python3.14.3t instead of PyQt6 install
$ pip install aqtinstall
in virtual environment of python3.14.3t

$ mkdir MULTITHREAD
$ cd 
MULTITHREAD
$ python3.14t -m venv .env
$ source .env/bin/activate
$ pip install aqtinstall
$ pip install --upgrade pip
$ pip install numpy matplotlib cxroots
 
Versions of modules from Python calculation based on principle of argument (theory of functions of a complex variable) , converted via Google's AI  to learn multi-threaded coding style in Python 3.14.3t .
 
cat complexThreaded01.py
import numpy as np
from cxroots import Circle
import threading
import logging
import os
import sys

# Silence internal library logs
logging.getLogger('cxroots').setLevel(logging.ERROR)

def analyze_circle(radius, f, df, t_vals):
   """Worker function to analyze a specific radius in parallel."""
   # 1. Manual Integration
   contour_points = radius * np.exp(1j * t_vals)
   fz = f(contour_points)
   dfz = df(contour_points)
   integrand = dfz / fz
   dz = np.diff(contour_points, append=contour_points[0])
   manual_count = int(np.round((np.sum(integrand * dz) / (2j * np.pi)).real))
    
   # 2. cxroots Calculation (Redirecting stdout to keep it clean)
   with open(os.devnull, 'w') as fnull:
       old_stdout = sys.stdout
       sys.stdout = fnull
       try:
           C = Circle(0, radius)
           roots = C.roots(f, df)
       finally:
           sys.stdout = old_stdout

   # Thread-safe printing of results
   output = (
       f"\n--- Results for Radius {radius} ---\n"
       f"Manual Count: {manual_count} zeros\n"
       f"{roots}\n"
   )
   print(output)

if __name__ == "__main__":
   f = lambda z: z**13 + 5*z + 2
   df = lambda z: 13*z**12 + 5
   t_vals = np.linspace(0, 2 * np.pi, 1000)

   print("The Argument Principle and Logarithmic Derivative (Parallel 3.14.3t)")
   print("f(z) = z**13 + 5*z + 2\n")

   # Define tasks for radius 3 and radius 1
   t1 = threading.Thread(target=analyze_circle, args=(3, f, df, t_vals))

   # Start parallel execution
   t1.start()

   # Wait for completion
   t1.join()

cat complexThreaded09.py
import numpy as np
from cxroots import Circle
import os
import matplotlib.pyplot as plt
import threading
import logging
import sys

# 1. Silence all library logging (cxroots, Matplotlib, Qt)
logging.getLogger('cxroots').setLevel(logging.ERROR)
os.environ["QT_LOGGING_RULES"] = "*.debug=false;qt.qpa.fonts.warning=false"

def count_zeros_worker(f, df, contour_points):
   # Perform math
   fz, dfz = f(contour_points), df(contour_points)
   integrand = dfz / fz
   dz = np.diff(contour_points, append=contour_points[0])
   count = int(np.round((np.sum(integrand * dz) / (2j * np.pi)).real))
    
   # Only this prints to console
   # print(f"Number of zeros (Manual): {count}")

def find_roots_worker(f, df, res):
   # Silence stdout locally to hide cxroots progress bars/info
   with open(os.devnull, 'w') as fnull:
       old_stdout = sys.stdout
       sys.stdout = fnull
       try:
           C = Circle(0, 4)
           roots = C.roots(f, df)
       finally:
           sys.stdout = old_stdout
            
   res['roots'] = roots
   print(f"Number of zeros (cxroots): {len(roots.roots)}")

if __name__ == "__main__":
   f = lambda z: z**13 + 5*z + 2
   df = lambda z: 13*z**12 + 5
   t_vals = np.linspace(0, 2 * np.pi, 1000)
   circle_pts = 4 * np.exp(1j * t_vals)
   shared_res = {}

   # Parallel threads in 3.14.3t
   t1 = threading.Thread(target=count_zeros_worker, args=(f, df, circle_pts))
   t2 = threading.Thread(target=find_roots_worker, args=(f, df, shared_res))

   t1.start()
   t2.start()
   t1.join()
   t2.join()


   # Show final plot
   if 'roots' in shared_res:
      shared_res['roots'].show()
 
Test on Debian Trixie 
 



Test on Debian Forky
 

  cat complexThreaded08.py
import os
import numpy as np
import matplotlib.pyplot as plt
from cxroots import Circle
from concurrent.futures import ThreadPoolExecutor

# Silence Qt warnings
os.environ["QT_LOGGING_RULES"] = "*.debug=false;qt.qpa.fonts.warning=false"

def count_zeros_task(f, df, contour_points):
   """Calculates zeros via the Argument Principle."""
   fz, dfz = f(contour_points), df(contour_points)
   integrand = dfz / fz
   dz = np.diff(contour_points, append=contour_points[0])
   integral = np.sum(integrand * dz)
   return int(np.round((integral / (2j * np.pi)).real))

def find_roots_task(contour, f, df):
   """Calculates specific root locations using cxroots."""
   return contour.roots(f, df)

# 1. Setup Data
f = lambda z: 4*z**5 + 4*z**3 - 4*z + 9
df = lambda z: 20*z**4 + 12*z**2 - 4

t = np.linspace(0, 2 * np.pi, 1000)
circle_pts = 4 * np.exp(1j * t)
C = Circle(0, 4)

print("Starting concurrent calculations...")

# 2. Parallel Execution
with ThreadPoolExecutor() as executor:
   # Submit both tasks to run simultaneously
   future_count = executor.submit(count_zeros_task, f, df, circle_pts)
   future_roots = executor.submit(find_roots_task, C, f, df)


   # Retrieve results (this waits for each to finish)
   zero_count = future_count.result()
   roots_result = future_roots.result()

# 3. Output and Visualization
print(f"\nVerification (Argument Principle): {zero_count} zeros found.")
print(f"Detailed Root Analysis:\n{roots_result}")

# Plotting must happen on the main thread
roots_result.show()
plt.show()






















cat complexThreaded10.py
import os
import numpy as np
import matplotlib.pyplot as plt
from cxroots import Circle
from concurrent.futures import ThreadPoolExecutor

# Silence Qt warnings
os.environ["QT_LOGGING_RULES"] = "*.debug=false;qt.qpa.fonts.warning=false"

def count_zeros_task(f, df, contour_points):
  """Calculates zeros via the Argument Principle."""
  fz, dfz = f(contour_points), df(contour_points)
  integrand = dfz / fz
  dz = np.diff(contour_points, append=contour_points[0])
  integral = np.sum(integrand * dz)
  return int(np.round((integral / (2j * np.pi)).real))

def find_roots_task(contour, f, df):
  """Calculates specific root locations using cxroots."""
  return contour.roots(f, df)

# 1. Setup Data
f = lambda z: z**13 + 5*z + 2
df = lambda z: 13*z**12 + 5

t = np.linspace(0, 2 * np.pi, 1000)
circle_pts = 4 * np.exp(1j * t)
C = Circle(0, 4)

print("Starting concurrent calculations...")

# 2. Parallel Execution
with ThreadPoolExecutor() as executor:
  # Submit both tasks to run simultaneously
  future_count = executor.submit(count_zeros_task, f, df, circle_pts)
  future_roots = executor.submit(find_roots_task, C, f, df)


  # Retrieve results (this waits for each to finish)
  zero_count = future_count.result()
  roots_result = future_roots.result()

# 3. Output and Visualization
print(f"\nVerification (Argument Principle): {zero_count} zeros found.")
print(f"Detailed Root Analysis:\n{roots_result}")

# Plotting must happen on the main thread
roots_result.show()
plt.show()
 

 

Monday, 30 March 2026

Python calculation based on principle of argument (theory of functions of a complex variable)

 Core issues experienced when attempting to debug python code below were resolved under guidance of Google's AI Assistant . 

Principle of Argument doesn't provide any information about values of polynomial zeros inside predefined circle as well as locations of these zeros on complex plane. Classic math just says how many polynomial zeros we get inside given circle and nothing else. 

 Python calculates the Principle of Argument (or argument principle in complex analysis) by computing the winding number, which equals the number of zeros minus poles inside a contour. This is implemented by evaluating the change in the argument (angle) of a function along a closed contour, usually using numpy for angle calculation.cxroots imported in python module provides object Circle having method roots to achieve the goal to get actual zeros values.

Areas of physics and engineering that require not only the number of zeros (roots) of a complex polynomial within a certain region, but their exact values as well, are typically those involving system stability analysis, resonant behavior, signal processing, and wave propagation. In these scenarios, the exact values determine system frequency, decay rates, and phase behavior.
 

 pythonComplex01.py

import numpy as np
from cxroots import Circle

def count_zeros(f, df, contour_points):
   """
   Counts zeros of f(z) within the region enclosed by contour_points.
   f: The analytic function
   df: The derivative of the function
   contour_points: Array of complex numbers forming a closed loop
   """

   # Evaluate f and f' at each point on the contour
   fz = f(contour_points)
   dfz = df(contour_points)
   # Calculate the integrand: f'(z) / f(z)
   integrand = dfz / fz
   # Calculate dz (the difference between consecutive points)
   dz = np.diff(contour_points, append=contour_points[0])
   # Compute the contour integral using the trapezoidal rule
   integral = np.sum(integrand * dz)
   # The result should be an integer
   return int(np.round((integral / (2j * np.pi)).real))

t = np.linspace(0, 2 * np.pi, 1000)
circle = 4 * np.exp(1j * t)

f = lambda z: z**4 + 4*z**3 - 8*z - 2
df = lambda z: 4*z**3 + 12*z**2 -8   
print("The Argument Principle and the Logarithmic Derivative in Complex Analysis\n")
print("f(z) = z**4 + 4*z**3 - 8*z - 2 ; df/dz(z) = 4*z**3 + 12*z**2 -8\n")
print(f"Number of zeros in circle of radius 4: {count_zeros(f, df, circle)}\n")
# Define a circle of radius 4 centered at the origin
C = Circle(0, 4)
# Find all roots within the circle
roots = C.roots(f, df)
print(roots,"\n")


circle = 1 * np.exp(1j * t)
print(f"Number of zeros in circle of radius 1: {count_zeros(f, df, circle)}\n")
# Define a circle of radius 3 centered at the origin
C = Circle(0, 1)
# Find all roots within the circle
roots = C.roots(f, df)
print(roots)


~/ComplexAnalysis
python  pythonComplex01.py
The Argument Principle and the Logarithmic Derivative in Complex Analysis

f(z) = z**4 + 4*z**3 - 8*z - 2 ; df/dz(z) = 4*z**3 + 12*z**2 -8

Number of zeros in circle of radius 4: 4

Multiplicity |               Root               
------------------------------------------------
     1       | -3.334414218339 +0.000000000000i
     1       | -1.741963784303 -0.000000000000i
     1       | -0.258036215697 +0.000000000000i
     1       |  1.334414218339 -0.000000000000i  

Number of zeros in circle of radius 1: 1

Multiplicity |               Root               
------------------------------------------------
     1       | -0.258036215697 +0.000000000000i

~/ComplexAnalysis

Case 2 

 > cat  pythonComplex02.py

import numpy as np
from cxroots import Circle

def count_zeros(f, df, contour_points):
   """
   Counts zeros of f(z) within the region enclosed by contour_points.
   f: The analytic function
   df: The derivative of the function
   contour_points: Array of complex numbers forming a closed loop
   """

   # Evaluate f and f' at each point on the contour
   fz = f(contour_points)
   dfz = df(contour_points)
   # Calculate the integrand: f'(z) / f(z)
   integrand = dfz / fz
   # Calculate dz (the difference between consecutive points)
   dz = np.diff(contour_points, append=contour_points[0])
   # Compute the contour integral using the trapezoidal rule
   integral = np.sum(integrand * dz)
   # The result should be an integer
   return int(np.round((integral / (2j * np.pi)).real))

t = np.linspace(0, 2 * np.pi, 1000)
circle = 3 * np.exp(1j * t)

f = lambda z: z**13 + 5*z + 2  
df = lambda z: 13*z**12 + 5   

print("The Argument Principle and the Logarithmic Derivative in Complex Analysis\n")
print("f(z) = z**13 +5*z +2  ; df/dz(z) = 13*z**12 + 5\n")
print(f"Number of zeros in circle of radius 3: {count_zeros(f, df, circle)}")
# Define a circle of radius 3 centered at the origin
C = Circle(0, 3)
# Find all roots within the circle
roots = C.roots(f, df)
print(roots)

circle = 1 * np.exp(1j * t)
print(f"Number of zeros in circle of radius 1: {count_zeros(f, df, circle)}")
# Define a circle of radius 3 centered at the origin
C = Circle(0, 1)
# Find all roots within the circle
roots = C.roots(f, df)
print(roots)

~/ComplexAnalysis
python  pythonComplex02.py
The Argument Principle and the Logarithmic Derivative in Complex Analysis

f(z) = z**13 +5*z +2  ; df/dz(z) = 13*z**12 + 5

Number of zeros in circle of radius 3: 13
RootError encountered when subdivding Annulus sector: center=0.000+0.000i, r0=1.129, r1=1.221, phi0=7.414, phi1=8.168 into:
Annulus sector: center=0.000+0.000i, r0=1.129, r1=1.156, phi0=7.414, phi1=8.168
Annulus sector: center=0.000+0.000i, r0=1.156, r1=1.221, phi0=7.414, phi1=8.168

 
Multiplicity |               Root               
------------------------------------------------
     1       | -1.063154526530 -0.299112694677i
     1       | -1.063154526530 +0.299112694677i
     1       | -0.771405797002 -0.815087403529i
     1       | -0.771405797002 +0.815087403529i
     1       | -0.399998657881 +0.000000000000i
     1       | -0.262722673288 -1.111020328751i
     1       | -0.262722673288 +1.111020328751i
     1       |  0.326597088580 -1.109580758477i
     1       |  0.326597088580 +1.109580758477i
     1       |  0.837706346436 -0.811700768559i
     1       |  0.837706346436 +0.811700768559i
     1       |  1.132978890745 +0.297012150385i
     1       |  1.132978890745 -0.297012150385i

 
Number of zeros in circle of radius 1: 1

 
Multiplicity |               Root               
------------------------------------------------
     1       | -0.399998657881 +0.000000000000i

======================================================= 

Now attempt plotting of samples below. First add libraries to python VENV

======================================================

> pip install PyQt6

> pip install matplotlib

cat pythonComplex04.py
import os
# Silence Qt font/logging warnings
os.environ["QT_LOGGING_RULES"] = "*.debug=false;qt.qpa.fonts.warning=false"

from  cxroots import  Circle
import matplotlib
import matplotlib.pyplot as plt

f = lambda z: z**4 + 4*z**3 - 8*z - 2
df = lambda z: 4*z**3 + 12*z**2 -8   

# 2. Define a contour (e.g., a circle with radius 4 centered at 0)
C = Circle(0, 4)

# 3. Plot the contour itself to verify the search region
# 4. Find roots and plot them within the contour
roots = C.roots(f, df)
print(roots)
roots.show()
plt.show()












> cat pythonComplex03.py
import os
# Silence Qt font/logging warnings
os.environ["QT_LOGGING_RULES"] = "*.debug=false;qt.qpa.fonts.warning=false"

from  cxroots import  Circle
import matplotlib
import matplotlib.pyplot as plt

f = lambda z: z**13 + 5*z + 2
df = lambda z: 13*z**12 + 5

# 2. Define a contour (e.g., a circle with radius 3 centered at 0)
C = Circle(0, 3)

# 3. Plot the contour itself to verify the search region
# 4. Find roots and plot them within the contour
roots = C.roots(f, df)
print(roots)
roots.show()
plt.show()













The script below counts number of zeros in circle of predefined radius, prints values of zeros been detected and pops up the plot containing locations of all zeros on complex plane.

cat pythonComplex07.py
import os
# Silence Qt font/logging warnings
os.environ["QT_LOGGING_RULES"] = "*.debug=false;qt.qpa.fonts.warning=false"

from  cxroots import  Circle
import matplotlib
import matplotlib.pyplot as plt
import numpy as np

def count_zeros(f, df, contour_points):
   """
   Counts zeros of f(z) within the region enclosed by contour_points.
   f: The analytic function
   df: The derivative of the function
   contour_points: Array of complex numbers forming a closed loop

   """
   # Evaluate f and f' at each point on the contour
   fz = f(contour_points)
   dfz = df(contour_points)
   # Calculate the integrand: f'(z) / f(z)
   integrand = dfz / fz
   # Calculate dz (the difference between consecutive points)
   dz = np.diff(contour_points, append=contour_points[0])
   # Compute the contour integral using the trapezoidal rule
   integral = np.sum(integrand * dz)
   # The result should be an integer
   return int(np.round((integral / (2j * np.pi)).real))

t = np.linspace(0, 2 * np.pi, 1000)
circle = 4 * np.exp(1j * t)

f = lambda z: 4*z**5 + 4*z**3 - 4*z + 9
df = lambda z: 20*z**4 + 12*z**2 - 4

print("The Argument Principle and the Logarithmic Derivative in Complex Analysis\n")
print("f(z) = 4*z**5 + 4*z**3 - 4*z + 9 ; df/dz(z) = 20*z**4 + 12*z**2 - 4\n")
print(f"Number of zeros in circle of radius 4: {count_zeros(f, df, circle)}\n")

# 2. Define a contour (e.g., a circle with radius 4 centered at 0)
C = Circle(0, 4)
# 3. Plot the contour itself to verify the search region
# 4. Find roots and plot them within the contour
roots = C.roots(f, df)
print(roots)
roots.show()
plt.show()


 Increasing radius from 3 to 4 fixes problem in 
pythonComplex02.py  and pythonComplex03.py

❯ cat pythonComplex09.py
import numpy as np
from cxroots import Circle
import os
# Silence Qt font/logging warnings
os.environ["QT_LOGGING_RULES"] = "*.debug=false;qt.qpa.fonts.warning=false"

import matplotlib
import matplotlib.pyplot as plt

def count_zeros(f, df, contour_points):
    """
    Counts zeros of f(z) within the region enclosed by contour_points.
    f: The analytic function
    df: The derivative of the function
    contour_points: Array of complex numbers forming a closed loop
    """

    # Evaluate f and f' at each point on the contour
    fz = f(contour_points)
    dfz = df(contour_points)
    # Calculate the integrand: f'(z) / f(z)
    integrand = dfz / fz
    # Calculate dz (the difference between consecutive points)
    dz = np.diff(contour_points, append=contour_points[0])
    # Compute the contour integral using the trapezoidal rule
    integral = np.sum(integrand * dz)
    # The result should be an integer
    return int(np.round((integral / (2j * np.pi)).real))

t = np.linspace(0, 2 * np.pi, 1000)
circle = 4 * np.exp(1j * t)

f = lambda z: z**13 + 5*z + 2
df = lambda z: 13*z**12 + 5

print("The Argument Principle and the Logarithmic Derivative in Complex Analysis\n")
print("f(z) = z**13 +5*z +2  ; df/dz(z) = 13*z**12 + 5\n")
print(f"Number of zeros in circle of radius 4: {count_zeros(f, df, circle)}\n")

# 2. Define a contour (e.g., a circle with radius 4 centered at 0)
C = Circle(0, 4)
# 3. Plot the contour itself to verify the search region
# 4. Find roots and plot them within the contour
roots = C.roots(f, df)
print(roots)
roots.show()
plt.show()


How many roots of f(z) = i*z^15 + z*sin(z) + z^3*exp(2*z) are in the right half-plane and how many are in the left ?

  Follow code proposed in  https://lxer.com/module/newswire/view/363645/index.html  .  Setup python3.14.3t on CachyOS along with aqtinstall ...