Description
When inspecting the Shur complementary portfolio, I encountered some issues.
In the formulation of your presentation this can be found:
with
By following the third step of the algorithm (Augment and allocate) starting from
precise/precise/skaters/portfoliostatic/schurportfactory.py
line 122
# 3. Augment and allocate
Ag, Dg, info = schur_augmentation(A=A, B=B, C=C, D=D, gamma=gamma) <--------HERE
precise/precise/skaters/portfoliostatic/schurportutil.py
, line 13
def schur_augmentation(A,B,C,D, gamma):
"""
Mess with A, D to try to incorporate some off-diag info
"""
if gamma>0.0:
max_gamma = _maximal_gamma(A=A, B=B, C=C, D=D)
augA, bA = pseudo_schur_complement(A=A, B=B, C=C, D=D, gamma=gamma * max_gamma) # <-------------HERE
augD, bD = pseudo_schur_complement(A=D, B=C, C=B, D=A, gamma=gamma * max_gamma) # <---------HERE TOO
augmentation_fail = False
if not is_positive_def(augA):
try:
Ag = nearest_pos_def(augA)
except np.linalg.LinAlgError:
augmentation_fail=True
else:
Ag = augA
if not is_positive_def(augD):
try:
Dg = nearest_pos_def(augD)
except np.linalg.LinAlgError:
augmentation_fail=True
else:
Dg = augD
if augmentation_fail:
print('Warning: augmentation failed')
reductionA = 1.0
reductionD = 1.0
reductionRatioA = 1.0
Ag = A
Dg = D
else:
reductionD = np.linalg.norm(Dg)/np.linalg.norm(D)
reductionA = np.linalg.norm(Ag)/np.linalg.norm(A)
reductionRatioA = reductionA/reductionD
else:
reductionRatioA = 1.0
reductionA = 1.0
reductionD = 1.0
Ag = A
Dg = D
info = {'reductionA': reductionA,
'reductionD': reductionD,
'reductionRatioA': reductionRatioA}
return Ag, Dg, info
We arrive at this pseudo_schur_complement function where
precise/precise/skaters/portfoliostatic/schurportutil.py
, line 57
def pseudo_schur_complement(A, B, C, D, gamma, lmbda=None, warn=False):
"""
Augmented cov matrix for "A" inspired by the Schur complement
"""
if lmbda is None:
lmbda=gamma
try:
Ac_raw = schur_complement(A=A, B=B, C=C, D=D, gamma=gamma)
nA = np.shape(A)[0]
nD = np.shape(D)[0]
Ac = to_symmetric(Ac_raw)
M = symmetric_step_up_matrix(n1=nA, n2=nD)
Mt = np.transpose(M)
BDinv = multiply_by_inverse(B, D, throw=False)
BDinvMt = np.dot(BDinv, Mt)
Ra = np.eye(nA) - lmbda * BDinvMt
Ag = inverse_multiply(Ra, Ac, throw=False, warn=False)
except np.linalg.LinAlgError:
if warn:
print('Pseudo-schur failed, falling back to A')
Ag = A
n = np.shape(A)[0]
b = np.ones(shape=(n,1))
return Ag, b
However after that the following operations are performed:
So if we assume that
Which does not match what I expect from the presentation:
- "Before performing inter-group allocation we make a different modification. We multiply the precision of
$A^c$ by$b_Ab_A^T$ element-wise (and similarly, multiply the precision of$D^c$ by$b_Db_D^T$ )".
Meaning:
Specifically I dont understand where
And again when we perform the sub allocation:
precise/precise/skaters/portfoliostatic/schurportfactory.py
lines 132 and 138
# Sub-allocate
wA = hierarchical_schur_complementary_portfolio(cov=Ag, port=port, port_kwargs=port_kwargs,
alloc=alloc, alloc_kwargs=alloc_kwargs,
splitter=splitter, splitter_kwargs=splitter_kwargs,
seriator=seriator, seriator_kwargs=seriator_kwargs,
seriation_depth = seriation_depth-1,
delta=delta, gamma=gamma)
wD = hierarchical_schur_complementary_portfolio(cov=Dg, port=port, port_kwargs=port_kwargs,
alloc=alloc, alloc_kwargs=alloc_kwargs,
splitter=splitter, splitter_kwargs=splitter_kwargs,
seriator=seriator, seriator_kwargs=seriator_kwargs,
seriation_depth=seriation_depth - 1,
delta=delta, gamma=gamma)
the same augmented matrix
precise/precise/skaters/portfoliostatic/schurportfactory.py
line 122
# 3. Augment and allocate
Ag, Dg, info = schur_augmentation(A=A, B=B, C=C, D=D, gamma=gamma)
aA, aD = alloc(covs=[Ag, Dg]) #<----------HERE
is also passed to the next "iteration", while on the slides I found:
- The intra-group allocation pertaining to block
$A$ is determined by covariance matrix$A_{/ b_A(\lambda)}^c$ . In this notation the vector$b_A(\lambda)=\overrightarrow{1}-\lambda B D^{-1} \overrightarrow{1}$ . The generalized Schur complement is$A^c(\gamma)=A-\gamma B D^{-1} C$ . The notation$A_{/ b}^c$ denotes$A^c /\left(b b^T\right)$ with division performed element-wise.