This Python package consists of:
- enhanced implementation of quasi-polynomial based rootfinder, algorithm for finding roots of given quasi polynomial in given rectangular region in complex plane [1], [2] enhanced with root-multiplicity heuristic and (in some cases) automatic region selection
- Spectral distribution properties of quasi-polynomials: (i) delay distribution diagram, (ii) exponential asymptotes of root chains, (iii) safe upper bound of neutral spectrum and (iv) spectrum envelope
- quasi-polynomial (and transfer function) algebra
- various functions for quickly visualizing results
For original MATLAB® implementation of old QPmR algorithm from 2012, we refer to this page.
[1] Vyhlidal, T., and Zítek, P. (2009). Mapping based algorithm for large-scale computation of quasi-polynomial zeros. IEEE Transactions on Automatic Control, 54(1), 171-177.
[2] Vyhlidal, T. and Zitek, P. (2014). QPmR-Quasi-polynomial root-finder: Algorithm update and examples Editors: Vyhídal T., Lafay J.F., Sipahi R., Sringer 2014.
Please, keep in mind that thisproject is still under development.
Title: QPmR Python Package
ID: QPmRpythonPackage
Version: 1.0
Project: Robotics and Advanced Industrial Production
Project No.: CZ.02.01.01/00/22_008/0004590
Project RO: 1.1-Optimal control of interconnected time-delay systems
Date: 20.9.2025
Authors: Adam Peichl; Tomas Vyhlidal
Keywords: rootfinding algorithm, exponential polynomial, quasi-polynomial, time delay system, spectrum
The QPmR v2 algorithm is designed to find all roots of the quasi-polynomial
located in the complex plane region
The following table may clarify quasi-polynomial representation:
This repository contains growing number of examples, we will follow with one from 2014 paper. Please note that matplotlib is not required (as qpmr is built on contourpy, which is dependency of matplotlib).
Find all the roots of the quasi-polynomial
located in region
import logging
import matplotlib.pyplot as plt
import numpy as np
from qpmr import qpmr
delays = np.array([0., 1])
coefs = np.array([[0., 1], [1, 0]])
region = [-10, 2, 0, 30]
roots, meta = qpmr(region, coefs, delays)
matlab_roots = np.array([-0.3181 + 1.3372j,
-2.0623 + 7.5886j,
-2.6532 +13.9492j,
-3.0202 +20.2725j,
-3.2878 +26.5805j,])
complex_grid = meta.complex_grid
value = meta.z_value
plt.figure()
plt.subplot(121)
plt.contour(np.real(complex_grid), np.imag(complex_grid), np.real(value), levels=[0], colors='blue')
plt.contour(np.real(complex_grid), np.imag(complex_grid), np.imag(value), levels=[0], colors='green')
plt.scatter(np.real(roots), np.imag(roots), marker="o", color="r")
plt.subplot(122)
plt.scatter(np.real(roots), np.imag(roots), marker="o", color="r")
plt.scatter(np.real(matlab_roots), np.imag(matlab_roots), marker="x", color="b")
plt.show()DEBUG:qpmr.qpmr_v2:Grid size not specified, setting as ds=0.36 (solved by heuristic)
DEBUG:qpmr.qpmr_v2:Estimated size of complex grid = 57600.0 bytes
DEBUG:qpmr.numerical_methods:Numerical Newton converged in 3/100 steps, last MAX(|res|) = 9.994753622376123e-09
DEBUG:qpmr.argument_principle:Using argument principle, contour integral = 5.020734859071829
DEBUG:qpmr.argument_principle:Using argument principle, contour integral = 5.020753819340232
Resulting in the following figure (left contours and roots, right roots compared with matlab output)
qpmr package has logger with NullHandler, you can for example use
logger = logging.getLogger("qpmr")
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)Please, cite the following article
@article{vyhlidal2009mapping,
title={Mapping based algorithm for large-scale computation of quasi-polynomial zeros},
author={Vyhlidal, Tomas and Z{\'\i}tek, Pavel},
journal={IEEE Transactions on Automatic Control},
volume={54},
number={1},
pages={171--177},
year={2009},
publisher={IEEE}
}
Alternatively, this chapter of book
@incollection{vyhlidal2014qpmr,
title={QPmR-Quasi-polynomial root-finder: Algorithm update and examples},
author={Vyhl{\'\i}dal, Tom{\'a}{\v{s}} and Z{\'\i}tek, Pavel},
booktitle={Delay Systems: From Theory to Numerics and Applications},
pages={299--312},
year={2014},
publisher={Springer}
}
Using pipy (check the version as software is being developed)
pip install qpmrFrom github
pip install qpmr@git+https://github.com/LockeErasmus/qpmrLocal install
pip install <path-to-qpmr>Clone repository
git clone https://github.com/LockeErasmus/qpmr.gitinstall from source with -e
pip install -e qpmrThis package is available under GNU GPLv3 license.