Coverage for src / cvx / risk / linalg / cholesky.py: 100%

5 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-09 03:39 +0000

1"""Cholesky decomposition utilities for covariance matrices. 

2 

3This module provides a function to compute the upper triangular Cholesky 

4decomposition of a positive definite covariance matrix. 

5 

6Example: 

7 Compute the Cholesky decomposition of a covariance matrix: 

8 

9 >>> import numpy as np 

10 >>> from cvx.risk.linalg import cholesky 

11 >>> # Create a positive definite matrix 

12 >>> cov = np.array([[4.0, 2.0], [2.0, 5.0]]) 

13 >>> # Compute upper triangular Cholesky factor 

14 >>> R = cholesky(cov) 

15 >>> # Verify: R.T @ R = cov 

16 >>> np.allclose(R.T @ R, cov) 

17 True 

18 

19""" 

20 

21# Copyright 2023 Stanford University Convex Optimization Group 

22# 

23# Licensed under the Apache License, Version 2.0 (the "License"); 

24# you may not use this file except in compliance with the License. 

25# You may obtain a copy of the License at 

26# 

27# http://www.apache.org/licenses/LICENSE-2.0 

28# 

29# Unless required by applicable law or agreed to in writing, software 

30# distributed under the License is distributed on an "AS IS" BASIS, 

31# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

32# See the License for the specific language governing permissions and 

33# limitations under the License. 

34from __future__ import annotations 

35 

36import numpy as np 

37from numpy.linalg import cholesky as _cholesky 

38 

39 

40def cholesky(cov: np.ndarray) -> np.ndarray: 

41 """Compute the upper triangular part of the Cholesky decomposition. 

42 

43 This function computes the Cholesky decomposition of a positive definite matrix 

44 and returns the upper triangular matrix R such that R^T @ R = cov. 

45 

46 The Cholesky decomposition is useful in portfolio optimization because it 

47 provides an efficient way to compute portfolio risk as ||R @ w||_2, where 

48 w is the portfolio weights vector. 

49 

50 Args: 

51 cov: A positive definite covariance matrix of shape (n, n). 

52 

53 Returns: 

54 The upper triangular Cholesky factor R of shape (n, n). 

55 

56 Example: 

57 Basic usage with a simple covariance matrix: 

58 

59 >>> import numpy as np 

60 >>> from cvx.risk.linalg import cholesky 

61 >>> # Identity matrix 

62 >>> cov = np.eye(3) 

63 >>> R = cholesky(cov) 

64 >>> np.allclose(R, np.eye(3)) 

65 True 

66 

67 With a more complex covariance matrix: 

68 

69 >>> cov = np.array([[1.0, 0.5, 0.0], 

70 ... [0.5, 1.0, 0.5], 

71 ... [0.0, 0.5, 1.0]]) 

72 >>> R = cholesky(cov) 

73 >>> np.allclose(R.T @ R, cov) 

74 True 

75 

76 Verify upper triangular structure: 

77 

78 >>> R = cholesky(np.array([[4.0, 2.0], [2.0, 5.0]])) 

79 >>> # R is upper triangular (zeros below diagonal) 

80 >>> bool(np.allclose(R[1, 0], 0.0)) 

81 True 

82 >>> bool(R[0, 0] > 0 and R[1, 1] > 0) # Positive diagonal 

83 True 

84 

85 Portfolio risk computation via Cholesky factor: 

86 

87 >>> cov = np.array([[0.04, 0.01], [0.01, 0.09]]) 

88 >>> R = cholesky(cov) 

89 >>> w = np.array([0.6, 0.4]) 

90 >>> # Risk via Cholesky: ||R @ w||_2 

91 >>> risk_chol = np.linalg.norm(R @ w) 

92 >>> # Risk via covariance: sqrt(w^T @ cov @ w) 

93 >>> risk_cov = np.sqrt(w @ cov @ w) 

94 >>> bool(np.isclose(risk_chol, risk_cov)) 

95 True 

96 

97 Relationship between upper (R) and lower (L) triangular factors: 

98 

99 >>> cov = np.array([[9.0, 3.0], [3.0, 5.0]]) 

100 >>> R = cholesky(cov) 

101 >>> L = np.linalg.cholesky(cov) # numpy returns lower triangular 

102 >>> # R = L^T 

103 >>> np.allclose(R, L.T) 

104 True 

105 >>> # Both reconstruct the covariance 

106 >>> np.allclose(L @ L.T, cov) 

107 True 

108 >>> np.allclose(R.T @ R, cov) 

109 True 

110 

111 Note: 

112 This function returns the upper triangular factor (R), whereas 

113 numpy.linalg.cholesky returns the lower triangular factor (L). 

114 The relationship is: L @ L^T = cov and R^T @ R = cov, where R = L^T. 

115 

116 """ 

117 return _cholesky(cov).transpose()