Reflect Zeroes of Rational Matrices
reflect_zeroes.Rd
Given a square, rational matrix \(x(z)\) and a set of zeroes of \(x(z)\),
the function reflect_zeroes
constructs a rational, allpass matrix
\(U(z)\) such that \(x(z)U(z)\) has zeroes which are the reciprocals
of the selected zeroes. The other zeroes of \(x(z)\) and the poles of
\(x(z)\) are not changed.
Usage
reflect_zeroes(x, zeroes, ...)
# S3 method for polm
reflect_zeroes(
x,
zeroes,
tol = sqrt(.Machine$double.eps),
check_zeroes = TRUE,
...
)
# S3 method for lmfd
reflect_zeroes(
x,
zeroes,
tol = sqrt(.Machine$double.eps),
check_zeroes = TRUE,
...
)
# S3 method for stsp
reflect_zeroes(x, zeroes, tol = sqrt(.Machine$double.eps), ...)
Arguments
- x
Square, rational matrix object (with real coefficients).
- zeroes
Complex or real vector of zeroes to be reflected. It is assumed that for complex conjugated pairs of roots, only one is contained in this vector.
- ...
Not used.
- tol
(double) Tolerance parameter used for the checks.
- check_zeroes
If
TRUE
then the procedure checks that the given zeroes are zeroes of the rational matrix \(x(z)\).
Value
Rational matrix object which represents the rational matrix
\(x(z)U(z)\) with the reflected zeroes. The object is of
the same class as the input object x
.
Note
The procedures are only implemented for rational matrices with real coefficients.
Therefore complex zeroes occur in complex conjugated pairs and such pairs are
jointly reflected to ensure that the result again has real coefficients.
Note however, that the argument zeroes
must only contain one
element of the pairs to be reflected.
In some degnerate cases the procedure(s) may run into numerical problems:
For polynomial matrices and matrices in lmfd
form,
the procedure assumes that the value of the matrix evaluated at
\(z=0\) is non singular. For the matrices in statespace form, zeroes
on (or close to) the unit circle are not allowed. In addition multiple
zeroes may lead to unreliable results.
See also
The procedure uses the helper functions blaschke
and make_allpass
. For reflecting poles, see
reflect_poles
.
Examples
# ###################################################################
# polynomial matrix
# construct a (2 x 2) polynomial matrix with degree 2
x = polm(array(c(1,0,
0,1,
-1,0,
0,0,
1,0.25,
0.75,-1), dim = c(2,2,3)))
x
#> ( 2 x 2 ) matrix polynomial with degree <= 2
#> z^0 [,1] [,2] z^1 [,1] [,2] z^2 [,1] [,2]
#> [1,] 1 0 -1 0 1.00 0.75
#> [2,] 0 1 0 0 0.25 -1.00
# determine zeroes of x(z)
( x_zeroes = zeroes(x) )
#> [1] 0.9236707+0.0000000i 0.4447071-0.8609171i 0.4447071+0.8609171i
#> [4] -0.9709796+0.0000000i
# evaluate the polynomial at the (real) zeroe x_zeroes[1]
( x_value = zvalue(x, x_zeroes[1]) )
#> [,1] [,2]
#> [1,] 0.9294969+0i 0.6398757+0i
#> [2,] 0.2132919+0i 0.1468324+0i
# Verify that the matrix evaluated at z = x_zeroes[1] is rank deficient
d = svd(x_value)$d
(min(d) < (max(d) * sqrt(.Machine$double.eps)))
#> [1] TRUE
# Reflect this zeroe at the unit circle and check the zeroes of the result
x1 = reflect_zeroes(x, x_zeroes[1])
r_zeroes = x_zeroes
r_zeroes[1] = 1 / r_zeroes[1]
x1_zeroes = zeroes(x1)
j = match_vectors(r_zeroes, x1_zeroes)
all.equal(r_zeroes, x1_zeroes[j])
#> [1] TRUE
# x_zeroes[2] and x_zeroes[3] form a pair of complex conjugated zeroes
( x_value = zvalue(x, x_zeroes[2]) )
#> [,1] [,2]
#> [1,] 0.01187902+0.0952052i -0.4075604-0.5742839i
#> [2,] -0.13585347-0.1914280i 1.5434139+0.7657119i
# Verify that the matrix evaluated at x_zeroes[2] is rank deficient
d = svd(x_value)$d
(min(d) < (max(d) * sqrt(.Machine$double.eps)))
#> [1] TRUE
# reflect the real zeroe x_zeroes[1] and this pair of
# complex conjugated zeroes at the unit circle and verify the result
x1 = reflect_zeroes(x, x_zeroes[c(1,2)])
r_zeroes = x_zeroes
r_zeroes[1:3] = 1 / r_zeroes[1:3]
x1_zeroes = zeroes(x1)
j = match_vectors(r_zeroes, x1_zeroes)
all.equal(r_zeroes, x1_zeroes[j])
#> [1] TRUE
# Check that the transformation matrix U (x1 = x %r% U) is all-pass
all.equal(zvalues(x) %r% Ht(zvalues(x)), zvalues(x1) %r% Ht(zvalues(x1)))
#> [1] TRUE
# ###################################################################
# rational matrix in LMFD form
set.seed(12345)
(x = test_lmfd(dim = c(3,3), degrees = c(2,2), digits = 2))
#> ( 3 x 3 ) left matrix fraction description a^(-1)(z) b(z) with degrees (p = 2, q = 2)
#> left factor a(z):
#> z^0 [,1] [,2] [,3] z^1 [,1] [,2] [,3] z^2 [,1] [,2] [,3]
#> [1,] 1 0 0 0.59 -0.45 0.63 -0.92 0.37 0.82
#> [2,] 0 1 0 0.71 0.61 -0.28 -0.12 0.52 -0.89
#> [3,] 0 0 1 -0.11 -1.82 -0.28 1.82 -0.75 -0.33
#> right factor b(z):
#> z^0 [,1] [,2] [,3] z^1 [,1] [,2] [,3] z^2 [,1] [,2] [,3]
#> [1,] 1.12 1.46 -1.60 0.62 0.81 1.63 -0.32 0.03 -1.06
#> [2,] 0.30 -0.64 1.81 0.61 2.20 0.25 -1.66 1.13 0.94
#> [3,] 0.78 -1.55 -0.48 -0.16 2.05 0.49 1.77 -2.38 0.85
(x_zeroes = zeroes(x))
#> [1] -0.4672627+0.0000000i 0.3378125-0.5740499i 0.3378125+0.5740499i
#> [4] 0.1408149-1.3499406i 0.1408149+1.3499406i 4.9799815+0.0000000i
# reflect all zeroes inside the unit circle
# note: for complex zeroes, select only one of the complex conjugated pair!
x1 = reflect_zeroes(x, x_zeroes[(abs(x_zeroes) <1) & (Im(x_zeroes) >=0 )])
r_zeroes = x_zeroes
r_zeroes[abs(r_zeroes) < 1] = 1 / r_zeroes[abs(r_zeroes) < 1]
(x1_zeroes = zeroes(x1))
#> [1] 0.140815-1.349941i 0.140815+1.349941i 0.761438-1.293923i
#> [4] 0.761438+1.293923i -2.140124+0.000000i 4.979981+0.000000i
j = match_vectors(r_zeroes, x1_zeroes)
all.equal(r_zeroes, x1_zeroes[j])
#> [1] TRUE
# Check that the transformation matrix U (x1 = x %r% U) is all-pass
all.equal(zvalues(x) %r% Ht(zvalues(x)), zvalues(x1) %r% Ht(zvalues(x1)))
#> [1] TRUE
set.seed(NULL)
# ###################################################################
# rational matrix in statespace form (stsp object)
# create a random (2,2) rational matrix in state space form with
# state dimension s=5
set.seed(12345)
(x = test_stsp(dim = c(2,2), s = 5))
#> statespace realization [2,2] with s = 5 states
#> s[1] s[2] s[3] s[4] s[5] u[1]
#> s[1] 0.5855288 -0.2761841 -0.7505320 1.4557851 0.6121235 0.49118828
#> s[2] 0.7094660 -0.2841597 0.8168998 -0.6443284 -0.1623110 -0.32408658
#> s[3] -0.1093033 -0.9193220 -0.8863575 -1.5531374 0.8118732 -1.66205024
#> s[4] -0.4534972 -0.1162478 -0.3315776 -1.5977095 2.1968335 1.76773385
#> s[5] 0.6058875 1.8173120 1.1207127 1.8050975 2.0491903 0.02580105
#> x[1] -1.8179560 0.3706279 0.2987237 -0.4816474 1.6324456 1.00000000
#> x[2] 0.6300986 0.5202165 0.7796219 0.6203798 0.2542712 0.00000000
#> u[2]
#> s[1] 1.1285108
#> s[2] -2.3803581
#> s[3] -1.0602656
#> s[4] 0.9371405
#> s[5] 0.8544517
#> x[1] 0.0000000
#> x[2] 1.0000000
# zeroes of x(z)
(x_zeroes = zeroes(x))
#> [1] 0.2849467-0.0302833i 0.2849467+0.0302833i -0.3112259-0.4083715i
#> [4] -0.3112259+0.4083715i -0.5438276+0.0000000i
# reflect all unstable zeroes (inside the unit circle)
# note: for complex zeroes, select only one of the complex conjugated pair!
x1 = reflect_zeroes(x, x_zeroes[(abs(x_zeroes) <1) & (Im(x_zeroes) >=0 )])
r_zeroes = x_zeroes
r_zeroes[abs(r_zeroes) < 1] = 1 / r_zeroes[abs(r_zeroes) < 1]
(x1_zeroes = zeroes(x1))
#> [1] -1.838818+0.000000i -1.180546-1.549040i -1.180546+1.549040i
#> [4] 3.470232-0.368805i 3.470232+0.368805i
j = match_vectors(r_zeroes, x1_zeroes)
all.equal(r_zeroes, x1_zeroes[j])
#> [1] TRUE
# Check that the transformation matrix U (x1 = x %r% U) is all-pass
all.equal(zvalues(x) %r% Ht(zvalues(x)), zvalues(x1) %r% Ht(zvalues(x1)))
#> [1] TRUE
set.seed(NULL)