Coverage for /usr/lib/python3/dist-packages/sympy/matrices/dense.py: 32%

169 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1import random 

2 

3from sympy.core.basic import Basic 

4from sympy.core.singleton import S 

5from sympy.core.symbol import Symbol 

6from sympy.core.sympify import sympify 

7from sympy.functions.elementary.trigonometric import cos, sin 

8from sympy.utilities.decorator import doctest_depends_on 

9from sympy.utilities.exceptions import sympy_deprecation_warning 

10from sympy.utilities.iterables import is_sequence 

11 

12from .common import ShapeError 

13from .decompositions import _cholesky, _LDLdecomposition 

14from .matrices import MatrixBase 

15from .repmatrix import MutableRepMatrix, RepMatrix 

16from .solvers import _lower_triangular_solve, _upper_triangular_solve 

17 

18 

19def _iszero(x): 

20 """Returns True if x is zero.""" 

21 return x.is_zero 

22 

23 

24class DenseMatrix(RepMatrix): 

25 """Matrix implementation based on DomainMatrix as the internal representation""" 

26 

27 # 

28 # DenseMatrix is a superclass for both MutableDenseMatrix and 

29 # ImmutableDenseMatrix. Methods shared by both classes but not for the 

30 # Sparse classes should be implemented here. 

31 # 

32 

33 is_MatrixExpr = False # type: bool 

34 

35 _op_priority = 10.01 

36 _class_priority = 4 

37 

38 @property 

39 def _mat(self): 

40 sympy_deprecation_warning( 

41 """ 

42 The private _mat attribute of Matrix is deprecated. Use the 

43 .flat() method instead. 

44 """, 

45 deprecated_since_version="1.9", 

46 active_deprecations_target="deprecated-private-matrix-attributes" 

47 ) 

48 

49 return self.flat() 

50 

51 def _eval_inverse(self, **kwargs): 

52 return self.inv(method=kwargs.get('method', 'GE'), 

53 iszerofunc=kwargs.get('iszerofunc', _iszero), 

54 try_block_diag=kwargs.get('try_block_diag', False)) 

55 

56 def as_immutable(self): 

57 """Returns an Immutable version of this Matrix 

58 """ 

59 from .immutable import ImmutableDenseMatrix as cls 

60 return cls._fromrep(self._rep.copy()) 

61 

62 def as_mutable(self): 

63 """Returns a mutable version of this matrix 

64 

65 Examples 

66 ======== 

67 

68 >>> from sympy import ImmutableMatrix 

69 >>> X = ImmutableMatrix([[1, 2], [3, 4]]) 

70 >>> Y = X.as_mutable() 

71 >>> Y[1, 1] = 5 # Can set values in Y 

72 >>> Y 

73 Matrix([ 

74 [1, 2], 

75 [3, 5]]) 

76 """ 

77 return Matrix(self) 

78 

79 def cholesky(self, hermitian=True): 

80 return _cholesky(self, hermitian=hermitian) 

81 

82 def LDLdecomposition(self, hermitian=True): 

83 return _LDLdecomposition(self, hermitian=hermitian) 

84 

85 def lower_triangular_solve(self, rhs): 

86 return _lower_triangular_solve(self, rhs) 

87 

88 def upper_triangular_solve(self, rhs): 

89 return _upper_triangular_solve(self, rhs) 

90 

91 cholesky.__doc__ = _cholesky.__doc__ 

92 LDLdecomposition.__doc__ = _LDLdecomposition.__doc__ 

93 lower_triangular_solve.__doc__ = _lower_triangular_solve.__doc__ 

94 upper_triangular_solve.__doc__ = _upper_triangular_solve.__doc__ 

95 

96 

97def _force_mutable(x): 

98 """Return a matrix as a Matrix, otherwise return x.""" 

99 if getattr(x, 'is_Matrix', False): 

100 return x.as_mutable() 

101 elif isinstance(x, Basic): 

102 return x 

103 elif hasattr(x, '__array__'): 

104 a = x.__array__() 

105 if len(a.shape) == 0: 

106 return sympify(a) 

107 return Matrix(x) 

108 return x 

109 

110 

111class MutableDenseMatrix(DenseMatrix, MutableRepMatrix): 

112 

113 def simplify(self, **kwargs): 

114 """Applies simplify to the elements of a matrix in place. 

115 

116 This is a shortcut for M.applyfunc(lambda x: simplify(x, ratio, measure)) 

117 

118 See Also 

119 ======== 

120 

121 sympy.simplify.simplify.simplify 

122 """ 

123 from sympy.simplify.simplify import simplify as _simplify 

124 for (i, j), element in self.todok().items(): 

125 self[i, j] = _simplify(element, **kwargs) 

126 

127 

128MutableMatrix = Matrix = MutableDenseMatrix 

129 

130########### 

131# Numpy Utility Functions: 

132# list2numpy, matrix2numpy, symmarray 

133########### 

134 

135 

136def list2numpy(l, dtype=object): # pragma: no cover 

137 """Converts Python list of SymPy expressions to a NumPy array. 

138 

139 See Also 

140 ======== 

141 

142 matrix2numpy 

143 """ 

144 from numpy import empty 

145 a = empty(len(l), dtype) 

146 for i, s in enumerate(l): 

147 a[i] = s 

148 return a 

149 

150 

151def matrix2numpy(m, dtype=object): # pragma: no cover 

152 """Converts SymPy's matrix to a NumPy array. 

153 

154 See Also 

155 ======== 

156 

157 list2numpy 

158 """ 

159 from numpy import empty 

160 a = empty(m.shape, dtype) 

161 for i in range(m.rows): 

162 for j in range(m.cols): 

163 a[i, j] = m[i, j] 

164 return a 

165 

166 

167########### 

168# Rotation matrices: 

169# rot_givens, rot_axis[123], rot_ccw_axis[123] 

170########### 

171 

172 

173def rot_givens(i, j, theta, dim=3): 

174 r"""Returns a a Givens rotation matrix, a a rotation in the 

175 plane spanned by two coordinates axes. 

176 

177 Explanation 

178 =========== 

179 

180 The Givens rotation corresponds to a generalization of rotation 

181 matrices to any number of dimensions, given by: 

182 

183 .. math:: 

184 G(i, j, \theta) = 

185 \begin{bmatrix} 

186 1 & \cdots & 0 & \cdots & 0 & \cdots & 0 \\ 

187 \vdots & \ddots & \vdots & & \vdots & & \vdots \\ 

188 0 & \cdots & c & \cdots & -s & \cdots & 0 \\ 

189 \vdots & & \vdots & \ddots & \vdots & & \vdots \\ 

190 0 & \cdots & s & \cdots & c & \cdots & 0 \\ 

191 \vdots & & \vdots & & \vdots & \ddots & \vdots \\ 

192 0 & \cdots & 0 & \cdots & 0 & \cdots & 1 

193 \end{bmatrix} 

194 

195 Where $c = \cos(\theta)$ and $s = \sin(\theta)$ appear at the intersections 

196 ``i``\th and ``j``\th rows and columns. 

197 

198 For fixed ``i > j``\, the non-zero elements of a Givens matrix are 

199 given by: 

200 

201 - $g_{kk} = 1$ for $k \ne i,\,j$ 

202 - $g_{kk} = c$ for $k = i,\,j$ 

203 - $g_{ji} = -g_{ij} = -s$ 

204 

205 Parameters 

206 ========== 

207 

208 i : int between ``0`` and ``dim - 1`` 

209 Represents first axis 

210 j : int between ``0`` and ``dim - 1`` 

211 Represents second axis 

212 dim : int bigger than 1 

213 Number of dimentions. Defaults to 3. 

214 

215 Examples 

216 ======== 

217 

218 >>> from sympy import pi, rot_givens 

219 

220 A counterclockwise rotation of pi/3 (60 degrees) around 

221 the third axis (z-axis): 

222 

223 >>> rot_givens(1, 0, pi/3) 

224 Matrix([ 

225 [ 1/2, -sqrt(3)/2, 0], 

226 [sqrt(3)/2, 1/2, 0], 

227 [ 0, 0, 1]]) 

228 

229 If we rotate by pi/2 (90 degrees): 

230 

231 >>> rot_givens(1, 0, pi/2) 

232 Matrix([ 

233 [0, -1, 0], 

234 [1, 0, 0], 

235 [0, 0, 1]]) 

236 

237 This can be generalized to any number 

238 of dimensions: 

239 

240 >>> rot_givens(1, 0, pi/2, dim=4) 

241 Matrix([ 

242 [0, -1, 0, 0], 

243 [1, 0, 0, 0], 

244 [0, 0, 1, 0], 

245 [0, 0, 0, 1]]) 

246 

247 References 

248 ========== 

249 

250 .. [1] https://en.wikipedia.org/wiki/Givens_rotation 

251 

252 See Also 

253 ======== 

254 

255 rot_axis1: Returns a rotation matrix for a rotation of theta (in radians) 

256 about the 1-axis (clockwise around the x axis) 

257 rot_axis2: Returns a rotation matrix for a rotation of theta (in radians) 

258 about the 2-axis (clockwise around the y axis) 

259 rot_axis3: Returns a rotation matrix for a rotation of theta (in radians) 

260 about the 3-axis (clockwise around the z axis) 

261 rot_ccw_axis1: Returns a rotation matrix for a rotation of theta (in radians) 

262 about the 1-axis (counterclockwise around the x axis) 

263 rot_ccw_axis2: Returns a rotation matrix for a rotation of theta (in radians) 

264 about the 2-axis (counterclockwise around the y axis) 

265 rot_ccw_axis3: Returns a rotation matrix for a rotation of theta (in radians) 

266 about the 3-axis (counterclockwise around the z axis) 

267 """ 

268 if not isinstance(dim, int) or dim < 2: 

269 raise ValueError('dim must be an integer biggen than one, ' 

270 'got {}.'.format(dim)) 

271 

272 if i == j: 

273 raise ValueError('i and j must be different, ' 

274 'got ({}, {})'.format(i, j)) 

275 

276 for ij in [i, j]: 

277 if not isinstance(ij, int) or ij < 0 or ij > dim - 1: 

278 raise ValueError('i and j must be integers between 0 and ' 

279 '{}, got i={} and j={}.'.format(dim-1, i, j)) 

280 

281 theta = sympify(theta) 

282 c = cos(theta) 

283 s = sin(theta) 

284 M = eye(dim) 

285 M[i, i] = c 

286 M[j, j] = c 

287 M[i, j] = s 

288 M[j, i] = -s 

289 return M 

290 

291 

292def rot_axis3(theta): 

293 r"""Returns a rotation matrix for a rotation of theta (in radians) 

294 about the 3-axis. 

295 

296 Explanation 

297 =========== 

298 

299 For a right-handed coordinate system, this corresponds to a 

300 clockwise rotation around the `z`-axis, given by: 

301 

302 .. math:: 

303 

304 R = \begin{bmatrix} 

305 \cos(\theta) & \sin(\theta) & 0 \\ 

306 -\sin(\theta) & \cos(\theta) & 0 \\ 

307 0 & 0 & 1 

308 \end{bmatrix} 

309 

310 Examples 

311 ======== 

312 

313 >>> from sympy import pi, rot_axis3 

314 

315 A rotation of pi/3 (60 degrees): 

316 

317 >>> theta = pi/3 

318 >>> rot_axis3(theta) 

319 Matrix([ 

320 [ 1/2, sqrt(3)/2, 0], 

321 [-sqrt(3)/2, 1/2, 0], 

322 [ 0, 0, 1]]) 

323 

324 If we rotate by pi/2 (90 degrees): 

325 

326 >>> rot_axis3(pi/2) 

327 Matrix([ 

328 [ 0, 1, 0], 

329 [-1, 0, 0], 

330 [ 0, 0, 1]]) 

331 

332 See Also 

333 ======== 

334 

335 rot_givens: Returns a Givens rotation matrix (generalized rotation for 

336 any number of dimensions) 

337 rot_ccw_axis3: Returns a rotation matrix for a rotation of theta (in radians) 

338 about the 3-axis (counterclockwise around the z axis) 

339 rot_axis1: Returns a rotation matrix for a rotation of theta (in radians) 

340 about the 1-axis (clockwise around the x axis) 

341 rot_axis2: Returns a rotation matrix for a rotation of theta (in radians) 

342 about the 2-axis (clockwise around the y axis) 

343 """ 

344 return rot_givens(0, 1, theta, dim=3) 

345 

346 

347def rot_axis2(theta): 

348 r"""Returns a rotation matrix for a rotation of theta (in radians) 

349 about the 2-axis. 

350 

351 Explanation 

352 =========== 

353 

354 For a right-handed coordinate system, this corresponds to a 

355 clockwise rotation around the `y`-axis, given by: 

356 

357 .. math:: 

358 

359 R = \begin{bmatrix} 

360 \cos(\theta) & 0 & -\sin(\theta) \\ 

361 0 & 1 & 0 \\ 

362 \sin(\theta) & 0 & \cos(\theta) 

363 \end{bmatrix} 

364 

365 Examples 

366 ======== 

367 

368 >>> from sympy import pi, rot_axis2 

369 

370 A rotation of pi/3 (60 degrees): 

371 

372 >>> theta = pi/3 

373 >>> rot_axis2(theta) 

374 Matrix([ 

375 [ 1/2, 0, -sqrt(3)/2], 

376 [ 0, 1, 0], 

377 [sqrt(3)/2, 0, 1/2]]) 

378 

379 If we rotate by pi/2 (90 degrees): 

380 

381 >>> rot_axis2(pi/2) 

382 Matrix([ 

383 [0, 0, -1], 

384 [0, 1, 0], 

385 [1, 0, 0]]) 

386 

387 See Also 

388 ======== 

389 

390 rot_givens: Returns a Givens rotation matrix (generalized rotation for 

391 any number of dimensions) 

392 rot_ccw_axis2: Returns a rotation matrix for a rotation of theta (in radians) 

393 about the 2-axis (clockwise around the y axis) 

394 rot_axis1: Returns a rotation matrix for a rotation of theta (in radians) 

395 about the 1-axis (counterclockwise around the x axis) 

396 rot_axis3: Returns a rotation matrix for a rotation of theta (in radians) 

397 about the 3-axis (counterclockwise around the z axis) 

398 """ 

399 return rot_givens(2, 0, theta, dim=3) 

400 

401 

402def rot_axis1(theta): 

403 r"""Returns a rotation matrix for a rotation of theta (in radians) 

404 about the 1-axis. 

405 

406 Explanation 

407 =========== 

408 

409 For a right-handed coordinate system, this corresponds to a 

410 clockwise rotation around the `x`-axis, given by: 

411 

412 .. math:: 

413 

414 R = \begin{bmatrix} 

415 1 & 0 & 0 \\ 

416 0 & \cos(\theta) & \sin(\theta) \\ 

417 0 & -\sin(\theta) & \cos(\theta) 

418 \end{bmatrix} 

419 

420 Examples 

421 ======== 

422 

423 >>> from sympy import pi, rot_axis1 

424 

425 A rotation of pi/3 (60 degrees): 

426 

427 >>> theta = pi/3 

428 >>> rot_axis1(theta) 

429 Matrix([ 

430 [1, 0, 0], 

431 [0, 1/2, sqrt(3)/2], 

432 [0, -sqrt(3)/2, 1/2]]) 

433 

434 If we rotate by pi/2 (90 degrees): 

435 

436 >>> rot_axis1(pi/2) 

437 Matrix([ 

438 [1, 0, 0], 

439 [0, 0, 1], 

440 [0, -1, 0]]) 

441 

442 See Also 

443 ======== 

444 

445 rot_givens: Returns a Givens rotation matrix (generalized rotation for 

446 any number of dimensions) 

447 rot_ccw_axis1: Returns a rotation matrix for a rotation of theta (in radians) 

448 about the 1-axis (counterclockwise around the x axis) 

449 rot_axis2: Returns a rotation matrix for a rotation of theta (in radians) 

450 about the 2-axis (clockwise around the y axis) 

451 rot_axis3: Returns a rotation matrix for a rotation of theta (in radians) 

452 about the 3-axis (clockwise around the z axis) 

453 """ 

454 return rot_givens(1, 2, theta, dim=3) 

455 

456 

457def rot_ccw_axis3(theta): 

458 r"""Returns a rotation matrix for a rotation of theta (in radians) 

459 about the 3-axis. 

460 

461 Explanation 

462 =========== 

463 

464 For a right-handed coordinate system, this corresponds to a 

465 counterclockwise rotation around the `z`-axis, given by: 

466 

467 .. math:: 

468 

469 R = \begin{bmatrix} 

470 \cos(\theta) & -\sin(\theta) & 0 \\ 

471 \sin(\theta) & \cos(\theta) & 0 \\ 

472 0 & 0 & 1 

473 \end{bmatrix} 

474 

475 Examples 

476 ======== 

477 

478 >>> from sympy import pi, rot_ccw_axis3 

479 

480 A rotation of pi/3 (60 degrees): 

481 

482 >>> theta = pi/3 

483 >>> rot_ccw_axis3(theta) 

484 Matrix([ 

485 [ 1/2, -sqrt(3)/2, 0], 

486 [sqrt(3)/2, 1/2, 0], 

487 [ 0, 0, 1]]) 

488 

489 If we rotate by pi/2 (90 degrees): 

490 

491 >>> rot_ccw_axis3(pi/2) 

492 Matrix([ 

493 [0, -1, 0], 

494 [1, 0, 0], 

495 [0, 0, 1]]) 

496 

497 See Also 

498 ======== 

499 

500 rot_givens: Returns a Givens rotation matrix (generalized rotation for 

501 any number of dimensions) 

502 rot_axis3: Returns a rotation matrix for a rotation of theta (in radians) 

503 about the 3-axis (clockwise around the z axis) 

504 rot_ccw_axis1: Returns a rotation matrix for a rotation of theta (in radians) 

505 about the 1-axis (counterclockwise around the x axis) 

506 rot_ccw_axis2: Returns a rotation matrix for a rotation of theta (in radians) 

507 about the 2-axis (counterclockwise around the y axis) 

508 """ 

509 return rot_givens(1, 0, theta, dim=3) 

510 

511 

512def rot_ccw_axis2(theta): 

513 r"""Returns a rotation matrix for a rotation of theta (in radians) 

514 about the 2-axis. 

515 

516 Explanation 

517 =========== 

518 

519 For a right-handed coordinate system, this corresponds to a 

520 counterclockwise rotation around the `y`-axis, given by: 

521 

522 .. math:: 

523 

524 R = \begin{bmatrix} 

525 \cos(\theta) & 0 & \sin(\theta) \\ 

526 0 & 1 & 0 \\ 

527 -\sin(\theta) & 0 & \cos(\theta) 

528 \end{bmatrix} 

529 

530 Examples 

531 ======== 

532 

533 >>> from sympy import pi, rot_ccw_axis2 

534 

535 A rotation of pi/3 (60 degrees): 

536 

537 >>> theta = pi/3 

538 >>> rot_ccw_axis2(theta) 

539 Matrix([ 

540 [ 1/2, 0, sqrt(3)/2], 

541 [ 0, 1, 0], 

542 [-sqrt(3)/2, 0, 1/2]]) 

543 

544 If we rotate by pi/2 (90 degrees): 

545 

546 >>> rot_ccw_axis2(pi/2) 

547 Matrix([ 

548 [ 0, 0, 1], 

549 [ 0, 1, 0], 

550 [-1, 0, 0]]) 

551 

552 See Also 

553 ======== 

554 

555 rot_givens: Returns a Givens rotation matrix (generalized rotation for 

556 any number of dimensions) 

557 rot_axis2: Returns a rotation matrix for a rotation of theta (in radians) 

558 about the 2-axis (clockwise around the y axis) 

559 rot_ccw_axis1: Returns a rotation matrix for a rotation of theta (in radians) 

560 about the 1-axis (counterclockwise around the x axis) 

561 rot_ccw_axis3: Returns a rotation matrix for a rotation of theta (in radians) 

562 about the 3-axis (counterclockwise around the z axis) 

563 """ 

564 return rot_givens(0, 2, theta, dim=3) 

565 

566 

567def rot_ccw_axis1(theta): 

568 r"""Returns a rotation matrix for a rotation of theta (in radians) 

569 about the 1-axis. 

570 

571 Explanation 

572 =========== 

573 

574 For a right-handed coordinate system, this corresponds to a 

575 counterclockwise rotation around the `x`-axis, given by: 

576 

577 .. math:: 

578 

579 R = \begin{bmatrix} 

580 1 & 0 & 0 \\ 

581 0 & \cos(\theta) & -\sin(\theta) \\ 

582 0 & \sin(\theta) & \cos(\theta) 

583 \end{bmatrix} 

584 

585 Examples 

586 ======== 

587 

588 >>> from sympy import pi, rot_ccw_axis1 

589 

590 A rotation of pi/3 (60 degrees): 

591 

592 >>> theta = pi/3 

593 >>> rot_ccw_axis1(theta) 

594 Matrix([ 

595 [1, 0, 0], 

596 [0, 1/2, -sqrt(3)/2], 

597 [0, sqrt(3)/2, 1/2]]) 

598 

599 If we rotate by pi/2 (90 degrees): 

600 

601 >>> rot_ccw_axis1(pi/2) 

602 Matrix([ 

603 [1, 0, 0], 

604 [0, 0, -1], 

605 [0, 1, 0]]) 

606 

607 See Also 

608 ======== 

609 

610 rot_givens: Returns a Givens rotation matrix (generalized rotation for 

611 any number of dimensions) 

612 rot_axis1: Returns a rotation matrix for a rotation of theta (in radians) 

613 about the 1-axis (clockwise around the x axis) 

614 rot_ccw_axis2: Returns a rotation matrix for a rotation of theta (in radians) 

615 about the 2-axis (counterclockwise around the y axis) 

616 rot_ccw_axis3: Returns a rotation matrix for a rotation of theta (in radians) 

617 about the 3-axis (counterclockwise around the z axis) 

618 """ 

619 return rot_givens(2, 1, theta, dim=3) 

620 

621 

622@doctest_depends_on(modules=('numpy',)) 

623def symarray(prefix, shape, **kwargs): # pragma: no cover 

624 r"""Create a numpy ndarray of symbols (as an object array). 

625 

626 The created symbols are named ``prefix_i1_i2_``... You should thus provide a 

627 non-empty prefix if you want your symbols to be unique for different output 

628 arrays, as SymPy symbols with identical names are the same object. 

629 

630 Parameters 

631 ---------- 

632 

633 prefix : string 

634 A prefix prepended to the name of every symbol. 

635 

636 shape : int or tuple 

637 Shape of the created array. If an int, the array is one-dimensional; for 

638 more than one dimension the shape must be a tuple. 

639 

640 \*\*kwargs : dict 

641 keyword arguments passed on to Symbol 

642 

643 Examples 

644 ======== 

645 These doctests require numpy. 

646 

647 >>> from sympy import symarray 

648 >>> symarray('', 3) 

649 [_0 _1 _2] 

650 

651 If you want multiple symarrays to contain distinct symbols, you *must* 

652 provide unique prefixes: 

653 

654 >>> a = symarray('', 3) 

655 >>> b = symarray('', 3) 

656 >>> a[0] == b[0] 

657 True 

658 >>> a = symarray('a', 3) 

659 >>> b = symarray('b', 3) 

660 >>> a[0] == b[0] 

661 False 

662 

663 Creating symarrays with a prefix: 

664 

665 >>> symarray('a', 3) 

666 [a_0 a_1 a_2] 

667 

668 For more than one dimension, the shape must be given as a tuple: 

669 

670 >>> symarray('a', (2, 3)) 

671 [[a_0_0 a_0_1 a_0_2] 

672 [a_1_0 a_1_1 a_1_2]] 

673 >>> symarray('a', (2, 3, 2)) 

674 [[[a_0_0_0 a_0_0_1] 

675 [a_0_1_0 a_0_1_1] 

676 [a_0_2_0 a_0_2_1]] 

677 <BLANKLINE> 

678 [[a_1_0_0 a_1_0_1] 

679 [a_1_1_0 a_1_1_1] 

680 [a_1_2_0 a_1_2_1]]] 

681 

682 For setting assumptions of the underlying Symbols: 

683 

684 >>> [s.is_real for s in symarray('a', 2, real=True)] 

685 [True, True] 

686 """ 

687 from numpy import empty, ndindex 

688 arr = empty(shape, dtype=object) 

689 for index in ndindex(shape): 

690 arr[index] = Symbol('%s_%s' % (prefix, '_'.join(map(str, index))), 

691 **kwargs) 

692 return arr 

693 

694 

695############### 

696# Functions 

697############### 

698 

699def casoratian(seqs, n, zero=True): 

700 """Given linear difference operator L of order 'k' and homogeneous 

701 equation Ly = 0 we want to compute kernel of L, which is a set 

702 of 'k' sequences: a(n), b(n), ... z(n). 

703 

704 Solutions of L are linearly independent iff their Casoratian, 

705 denoted as C(a, b, ..., z), do not vanish for n = 0. 

706 

707 Casoratian is defined by k x k determinant:: 

708 

709 + a(n) b(n) . . . z(n) + 

710 | a(n+1) b(n+1) . . . z(n+1) | 

711 | . . . . | 

712 | . . . . | 

713 | . . . . | 

714 + a(n+k-1) b(n+k-1) . . . z(n+k-1) + 

715 

716 It proves very useful in rsolve_hyper() where it is applied 

717 to a generating set of a recurrence to factor out linearly 

718 dependent solutions and return a basis: 

719 

720 >>> from sympy import Symbol, casoratian, factorial 

721 >>> n = Symbol('n', integer=True) 

722 

723 Exponential and factorial are linearly independent: 

724 

725 >>> casoratian([2**n, factorial(n)], n) != 0 

726 True 

727 

728 """ 

729 

730 seqs = list(map(sympify, seqs)) 

731 

732 if not zero: 

733 f = lambda i, j: seqs[j].subs(n, n + i) 

734 else: 

735 f = lambda i, j: seqs[j].subs(n, i) 

736 

737 k = len(seqs) 

738 

739 return Matrix(k, k, f).det() 

740 

741 

742def eye(*args, **kwargs): 

743 """Create square identity matrix n x n 

744 

745 See Also 

746 ======== 

747 

748 diag 

749 zeros 

750 ones 

751 """ 

752 

753 return Matrix.eye(*args, **kwargs) 

754 

755 

756def diag(*values, strict=True, unpack=False, **kwargs): 

757 """Returns a matrix with the provided values placed on the 

758 diagonal. If non-square matrices are included, they will 

759 produce a block-diagonal matrix. 

760 

761 Examples 

762 ======== 

763 

764 This version of diag is a thin wrapper to Matrix.diag that differs 

765 in that it treats all lists like matrices -- even when a single list 

766 is given. If this is not desired, either put a `*` before the list or 

767 set `unpack=True`. 

768 

769 >>> from sympy import diag 

770 

771 >>> diag([1, 2, 3], unpack=True) # = diag(1,2,3) or diag(*[1,2,3]) 

772 Matrix([ 

773 [1, 0, 0], 

774 [0, 2, 0], 

775 [0, 0, 3]]) 

776 

777 >>> diag([1, 2, 3]) # a column vector 

778 Matrix([ 

779 [1], 

780 [2], 

781 [3]]) 

782 

783 See Also 

784 ======== 

785 .common.MatrixCommon.eye 

786 .common.MatrixCommon.diagonal 

787 .common.MatrixCommon.diag 

788 .expressions.blockmatrix.BlockMatrix 

789 """ 

790 return Matrix.diag(*values, strict=strict, unpack=unpack, **kwargs) 

791 

792 

793def GramSchmidt(vlist, orthonormal=False): 

794 """Apply the Gram-Schmidt process to a set of vectors. 

795 

796 Parameters 

797 ========== 

798 

799 vlist : List of Matrix 

800 Vectors to be orthogonalized for. 

801 

802 orthonormal : Bool, optional 

803 If true, return an orthonormal basis. 

804 

805 Returns 

806 ======= 

807 

808 vlist : List of Matrix 

809 Orthogonalized vectors 

810 

811 Notes 

812 ===== 

813 

814 This routine is mostly duplicate from ``Matrix.orthogonalize``, 

815 except for some difference that this always raises error when 

816 linearly dependent vectors are found, and the keyword ``normalize`` 

817 has been named as ``orthonormal`` in this function. 

818 

819 See Also 

820 ======== 

821 

822 .matrices.MatrixSubspaces.orthogonalize 

823 

824 References 

825 ========== 

826 

827 .. [1] https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process 

828 """ 

829 return MutableDenseMatrix.orthogonalize( 

830 *vlist, normalize=orthonormal, rankcheck=True 

831 ) 

832 

833 

834def hessian(f, varlist, constraints=()): 

835 """Compute Hessian matrix for a function f wrt parameters in varlist 

836 which may be given as a sequence or a row/column vector. A list of 

837 constraints may optionally be given. 

838 

839 Examples 

840 ======== 

841 

842 >>> from sympy import Function, hessian, pprint 

843 >>> from sympy.abc import x, y 

844 >>> f = Function('f')(x, y) 

845 >>> g1 = Function('g')(x, y) 

846 >>> g2 = x**2 + 3*y 

847 >>> pprint(hessian(f, (x, y), [g1, g2])) 

848 [ d d ] 

849 [ 0 0 --(g(x, y)) --(g(x, y)) ] 

850 [ dx dy ] 

851 [ ] 

852 [ 0 0 2*x 3 ] 

853 [ ] 

854 [ 2 2 ] 

855 [d d d ] 

856 [--(g(x, y)) 2*x ---(f(x, y)) -----(f(x, y))] 

857 [dx 2 dy dx ] 

858 [ dx ] 

859 [ ] 

860 [ 2 2 ] 

861 [d d d ] 

862 [--(g(x, y)) 3 -----(f(x, y)) ---(f(x, y)) ] 

863 [dy dy dx 2 ] 

864 [ dy ] 

865 

866 References 

867 ========== 

868 

869 .. [1] https://en.wikipedia.org/wiki/Hessian_matrix 

870 

871 See Also 

872 ======== 

873 

874 sympy.matrices.matrices.MatrixCalculus.jacobian 

875 wronskian 

876 """ 

877 # f is the expression representing a function f, return regular matrix 

878 if isinstance(varlist, MatrixBase): 

879 if 1 not in varlist.shape: 

880 raise ShapeError("`varlist` must be a column or row vector.") 

881 if varlist.cols == 1: 

882 varlist = varlist.T 

883 varlist = varlist.tolist()[0] 

884 if is_sequence(varlist): 

885 n = len(varlist) 

886 if not n: 

887 raise ShapeError("`len(varlist)` must not be zero.") 

888 else: 

889 raise ValueError("Improper variable list in hessian function") 

890 if not getattr(f, 'diff'): 

891 # check differentiability 

892 raise ValueError("Function `f` (%s) is not differentiable" % f) 

893 m = len(constraints) 

894 N = m + n 

895 out = zeros(N) 

896 for k, g in enumerate(constraints): 

897 if not getattr(g, 'diff'): 

898 # check differentiability 

899 raise ValueError("Function `f` (%s) is not differentiable" % f) 

900 for i in range(n): 

901 out[k, i + m] = g.diff(varlist[i]) 

902 for i in range(n): 

903 for j in range(i, n): 

904 out[i + m, j + m] = f.diff(varlist[i]).diff(varlist[j]) 

905 for i in range(N): 

906 for j in range(i + 1, N): 

907 out[j, i] = out[i, j] 

908 return out 

909 

910 

911def jordan_cell(eigenval, n): 

912 """ 

913 Create a Jordan block: 

914 

915 Examples 

916 ======== 

917 

918 >>> from sympy import jordan_cell 

919 >>> from sympy.abc import x 

920 >>> jordan_cell(x, 4) 

921 Matrix([ 

922 [x, 1, 0, 0], 

923 [0, x, 1, 0], 

924 [0, 0, x, 1], 

925 [0, 0, 0, x]]) 

926 """ 

927 

928 return Matrix.jordan_block(size=n, eigenvalue=eigenval) 

929 

930 

931def matrix_multiply_elementwise(A, B): 

932 """Return the Hadamard product (elementwise product) of A and B 

933 

934 >>> from sympy import Matrix, matrix_multiply_elementwise 

935 >>> A = Matrix([[0, 1, 2], [3, 4, 5]]) 

936 >>> B = Matrix([[1, 10, 100], [100, 10, 1]]) 

937 >>> matrix_multiply_elementwise(A, B) 

938 Matrix([ 

939 [ 0, 10, 200], 

940 [300, 40, 5]]) 

941 

942 See Also 

943 ======== 

944 

945 sympy.matrices.common.MatrixCommon.__mul__ 

946 """ 

947 return A.multiply_elementwise(B) 

948 

949 

950def ones(*args, **kwargs): 

951 """Returns a matrix of ones with ``rows`` rows and ``cols`` columns; 

952 if ``cols`` is omitted a square matrix will be returned. 

953 

954 See Also 

955 ======== 

956 

957 zeros 

958 eye 

959 diag 

960 """ 

961 

962 if 'c' in kwargs: 

963 kwargs['cols'] = kwargs.pop('c') 

964 

965 return Matrix.ones(*args, **kwargs) 

966 

967 

968def randMatrix(r, c=None, min=0, max=99, seed=None, symmetric=False, 

969 percent=100, prng=None): 

970 """Create random matrix with dimensions ``r`` x ``c``. If ``c`` is omitted 

971 the matrix will be square. If ``symmetric`` is True the matrix must be 

972 square. If ``percent`` is less than 100 then only approximately the given 

973 percentage of elements will be non-zero. 

974 

975 The pseudo-random number generator used to generate matrix is chosen in the 

976 following way. 

977 

978 * If ``prng`` is supplied, it will be used as random number generator. 

979 It should be an instance of ``random.Random``, or at least have 

980 ``randint`` and ``shuffle`` methods with same signatures. 

981 * if ``prng`` is not supplied but ``seed`` is supplied, then new 

982 ``random.Random`` with given ``seed`` will be created; 

983 * otherwise, a new ``random.Random`` with default seed will be used. 

984 

985 Examples 

986 ======== 

987 

988 >>> from sympy import randMatrix 

989 >>> randMatrix(3) # doctest:+SKIP 

990 [25, 45, 27] 

991 [44, 54, 9] 

992 [23, 96, 46] 

993 >>> randMatrix(3, 2) # doctest:+SKIP 

994 [87, 29] 

995 [23, 37] 

996 [90, 26] 

997 >>> randMatrix(3, 3, 0, 2) # doctest:+SKIP 

998 [0, 2, 0] 

999 [2, 0, 1] 

1000 [0, 0, 1] 

1001 >>> randMatrix(3, symmetric=True) # doctest:+SKIP 

1002 [85, 26, 29] 

1003 [26, 71, 43] 

1004 [29, 43, 57] 

1005 >>> A = randMatrix(3, seed=1) 

1006 >>> B = randMatrix(3, seed=2) 

1007 >>> A == B 

1008 False 

1009 >>> A == randMatrix(3, seed=1) 

1010 True 

1011 >>> randMatrix(3, symmetric=True, percent=50) # doctest:+SKIP 

1012 [77, 70, 0], 

1013 [70, 0, 0], 

1014 [ 0, 0, 88] 

1015 """ 

1016 # Note that ``Random()`` is equivalent to ``Random(None)`` 

1017 prng = prng or random.Random(seed) 

1018 

1019 if c is None: 

1020 c = r 

1021 

1022 if symmetric and r != c: 

1023 raise ValueError('For symmetric matrices, r must equal c, but %i != %i' % (r, c)) 

1024 

1025 ij = range(r * c) 

1026 if percent != 100: 

1027 ij = prng.sample(ij, int(len(ij)*percent // 100)) 

1028 

1029 m = zeros(r, c) 

1030 

1031 if not symmetric: 

1032 for ijk in ij: 

1033 i, j = divmod(ijk, c) 

1034 m[i, j] = prng.randint(min, max) 

1035 else: 

1036 for ijk in ij: 

1037 i, j = divmod(ijk, c) 

1038 if i <= j: 

1039 m[i, j] = m[j, i] = prng.randint(min, max) 

1040 

1041 return m 

1042 

1043 

1044def wronskian(functions, var, method='bareiss'): 

1045 """ 

1046 Compute Wronskian for [] of functions 

1047 

1048 :: 

1049 

1050 | f1 f2 ... fn | 

1051 | f1' f2' ... fn' | 

1052 | . . . . | 

1053 W(f1, ..., fn) = | . . . . | 

1054 | . . . . | 

1055 | (n) (n) (n) | 

1056 | D (f1) D (f2) ... D (fn) | 

1057 

1058 see: https://en.wikipedia.org/wiki/Wronskian 

1059 

1060 See Also 

1061 ======== 

1062 

1063 sympy.matrices.matrices.MatrixCalculus.jacobian 

1064 hessian 

1065 """ 

1066 

1067 functions = [sympify(f) for f in functions] 

1068 n = len(functions) 

1069 if n == 0: 

1070 return S.One 

1071 W = Matrix(n, n, lambda i, j: functions[i].diff(var, j)) 

1072 return W.det(method) 

1073 

1074 

1075def zeros(*args, **kwargs): 

1076 """Returns a matrix of zeros with ``rows`` rows and ``cols`` columns; 

1077 if ``cols`` is omitted a square matrix will be returned. 

1078 

1079 See Also 

1080 ======== 

1081 

1082 ones 

1083 eye 

1084 diag 

1085 """ 

1086 

1087 if 'c' in kwargs: 

1088 kwargs['cols'] = kwargs.pop('c') 

1089 

1090 return Matrix.zeros(*args, **kwargs)