Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703

704

705

706

707

708

709

710

711

712

713

714

715

716

717

718

719

720

721

722

723

724

725

726

727

728

729

730

731

732

733

734

735

736

737

738

739

740

741

742

743

744

745

746

747

748

749

750

751

752

753

754

755

756

757

758

759

760

761

762

763

764

765

766

767

768

769

770

771

772

773

774

775

776

777

778

779

780

781

782

783

784

785

786

787

788

789

790

791

792

793

794

795

796

797

798

799

800

801

802

803

804

805

806

807

808

809

810

811

812

813

814

815

816

817

818

819

820

821

822

823

824

825

826

827

828

829

830

831

832

833

834

835

836

837

838

839

840

841

842

843

844

845

846

847

848

849

850

851

852

853

854

855

856

857

858

859

860

861

862

863

864

865

866

867

868

869

870

871

872

873

874

875

876

877

878

879

880

881

882

883

884

885

886

887

888

889

890

891

892

893

894

895

896

897

898

899

900

901

902

903

904

905

906

907

908

909

910

911

912

913

914

915

916

917

918

919

920

921

922

923

924

925

926

927

928

929

930

931

932

933

934

935

936

937

938

939

940

941

942

943

944

945

946

947

948

949

950

951

952

953

954

955

956

957

958

959

960

961

962

963

964

965

966

967

968

969

970

971

972

973

974

975

976

977

978

979

980

981

982

983

984

985

986

987

988

989

990

991

992

993

994

995

996

997

998

999

1000

1001

1002

1003

1004

1005

1006

1007

1008

1009

1010

1011

1012

1013

1014

1015

1016

1017

1018

1019

1020

1021

1022

1023

1024

1025

1026

1027

1028

1029

1030

1031

1032

1033

1034

1035

1036

1037

1038

1039

1040

1041

1042

1043

1044

1045

1046

1047

1048

1049

1050

1051

1052

1053

1054

1055

1056

1057

1058

1059

1060

1061

1062

1063

1064

1065

1066

1067

1068

1069

1070

1071

1072

1073

1074

1075

1076

1077

1078

1079

1080

1081

1082

1083

1084

1085

1086

1087

1088

1089

1090

1091

1092

1093

1094

1095

1096

1097

1098

1099

1100

1101

1102

1103

1104

1105

1106

1107

1108

1109

1110

1111

1112

1113

1114

1115

1116

1117

1118

1119

1120

1121

1122

1123

1124

1125

1126

1127

1128

1129

1130

1131

1132

1133

1134

1135

1136

1137

1138

1139

1140

1141

1142

1143

1144

1145

1146

1147

1148

1149

1150

1151

1152

1153

1154

1155

1156

1157

1158

1159

1160

1161

1162

1163

1164

1165

1166

1167

1168

1169

1170

1171

1172

1173

1174

1175

1176

1177

1178

1179

1180

1181

1182

1183

1184

1185

1186

1187

1188

1189

1190

1191

1192

1193

1194

1195

1196

1197

1198

1199

1200

1201

1202

1203

1204

1205

1206

1207

1208

1209

1210

1211

1212

1213

1214

1215

1216

1217

1218

1219

1220

1221

1222

1223

1224

1225

1226

1227

1228

1229

1230

1231

1232

1233

1234

1235

1236

1237

1238

1239

1240

1241

1242

1243

1244

1245

1246

1247

1248

1249

1250

1251

1252

1253

1254

1255

1256

1257

1258

1259

1260

1261

1262

1263

1264

1265

1266

1267

1268

1269

1270

1271

1272

1273

1274

1275

1276

1277

1278

1279

1280

1281

1282

1283

1284

1285

1286

1287

1288

1289

1290

1291

1292

1293

1294

1295

1296

1297

1298

1299

1300

1301

1302

1303

1304

1305

1306

1307

1308

1309

1310

1311

1312

1313

1314

1315

1316

1317

1318

1319

1320

1321

1322

1323

1324

1325

1326

1327

1328

1329

1330

1331

1332

1333

1334

1335

1336

1337

1338

1339

1340

1341

1342

1343

1344

1345

1346

1347

1348

1349

1350

1351

1352

1353

1354

1355

1356

1357

1358

1359

1360

1361

1362

1363

1364

1365

1366

1367

1368

1369

1370

1371

1372

1373

1374

1375

1376

1377

1378

1379

1380

1381

1382

1383

1384

1385

1386

1387

1388

1389

1390

1391

1392

1393

1394

1395

1396

1397

1398

1399

1400

1401

1402

1403

1404

1405

1406

1407

1408

1409

1410

1411

1412

1413

1414

1415

1416

1417

1418

1419

1420

1421

1422

1423

1424

1425

1426

1427

1428

1429

1430

1431

1432

1433

1434

1435

1436

1437

1438

1439

1440

1441

1442

1443

1444

1445

1446

1447

1448

1449

1450

1451

1452

1453

1454

1455

1456

1457

1458

1459

1460

1461

1462

1463

1464

1465

1466

1467

1468

1469

1470

1471

1472

1473

1474

1475

1476

1477

1478

1479

1480

1481

1482

1483

1484

1485

1486

1487

1488

1489

1490

1491

1492

1493

1494

1495

1496

1497

1498

1499

1500

1501

1502

1503

1504

1505

1506

1507

1508

1509

1510

1511

1512

1513

1514

1515

1516

1517

1518

1519

1520

1521

1522

1523

1524

1525

1526

1527

1528

1529

1530

1531

1532

1533

1534

1535

1536

1537

1538

1539

1540

1541

1542

1543

1544

1545

1546

1547

1548

1549

1550

1551

1552

1553

1554

1555

1556

1557

1558

1559

1560

1561

1562

1563

1564

1565

1566

1567

1568

1569

1570

1571

1572

1573

1574

1575

1576

1577

1578

1579

1580

1581

1582

1583

1584

1585

1586

1587

1588

1589

1590

1591

1592

1593

1594

1595

1596

1597

1598

1599

1600

1601

1602

1603

1604

1605

1606

1607

1608

1609

1610

1611

1612

1613

1614

1615

1616

1617

1618

1619

1620

1621

1622

1623

1624

1625

1626

1627

1628

1629

1630

1631

1632

1633

1634

1635

1636

1637

1638

1639

1640

1641

1642

1643

1644

1645

1646

1647

1648

1649

1650

1651

1652

1653

1654

1655

1656

1657

1658

1659

1660

1661

1662

1663

1664

1665

1666

1667

1668

1669

1670

1671

1672

1673

1674

1675

1676

1677

1678

1679

1680

1681

1682

1683

1684

1685

1686

1687

1688

1689

1690

1691

1692

1693

1694

1695

1696

1697

1698

1699

1700

1701

1702

1703

1704

1705

1706

1707

1708

1709

1710

1711

1712

1713

1714

1715

1716

1717

1718

1719

1720

1721

1722

1723

1724

1725

1726

1727

1728

1729

1730

1731

1732

1733

1734

1735

1736

1737

1738

1739

1740

1741

1742

1743

1744

1745

1746

1747

1748

1749

1750

1751

1752

1753

1754

1755

1756

1757

1758

1759

1760

1761

1762

1763

1764

1765

1766

1767

1768

1769

1770

1771

1772

1773

1774

1775

1776

1777

1778

1779

1780

1781

1782

1783

1784

1785

1786

1787

1788

1789

1790

1791

1792

1793

1794

1795

1796

1797

1798

1799

1800

1801

1802

1803

1804

1805

1806

1807

1808

1809

1810

1811

1812

1813

1814

1815

1816

1817

1818

1819

1820

1821

1822

1823

1824

1825

1826

1827

1828

1829

1830

1831

1832

1833

1834

1835

1836

1837

1838

1839

1840

1841

1842

1843

1844

1845

1846

1847

1848

1849

1850

1851

1852

1853

1854

1855

1856

1857

1858

1859

1860

1861

1862

1863

1864

1865

1866

1867

1868

1869

1870

1871

1872

1873

1874

1875

1876

1877

1878

1879

1880

1881

1882

1883

1884

1885

1886

1887

1888

1889

1890

1891

1892

1893

1894

1895

1896

1897

1898

1899

1900

1901

1902

1903

1904

1905

1906

1907

1908

1909

1910

1911

1912

1913

1914

1915

1916

1917

1918

1919

1920

1921

1922

1923

1924

1925

1926

1927

1928

1929

1930

1931

1932

1933

1934

1935

1936

1937

1938

1939

1940

1941

1942

1943

1944

1945

1946

1947

1948

1949

1950

1951

1952

1953

1954

1955

1956

1957

1958

1959

1960

1961

1962

1963

1964

1965

1966

1967

1968

1969

1970

1971

1972

1973

1974

1975

1976

1977

1978

1979

1980

1981

1982

1983

1984

1985

1986

1987

1988

1989

1990

1991

1992

1993

1994

1995

1996

1997

1998

1999

2000

2001

2002

2003

2004

2005

2006

2007

2008

2009

2010

2011

2012

2013

2014

2015

2016

2017

2018

2019

2020

2021

2022

2023

2024

2025

2026

2027

2028

2029

2030

2031

2032

2033

2034

2035

2036

2037

2038

2039

2040

2041

2042

2043

2044

2045

2046

2047

2048

2049

2050

2051

2052

2053

2054

2055

2056

2057

2058

2059

2060

2061

2062

2063

2064

2065

2066

2067

2068

2069

2070

2071

2072

2073

2074

2075

2076

2077

2078

2079

2080

2081

2082

2083

2084

2085

2086

2087

2088

2089

2090

2091

2092

2093

2094

2095

2096

2097

2098

2099

2100

2101

2102

2103

2104

2105

2106

2107

2108

2109

2110

2111

2112

2113

2114

2115

2116

2117

2118

2119

2120

2121

2122

2123

2124

2125

2126

2127

2128

2129

2130

2131

2132

2133

2134

2135

2136

2137

2138

2139

2140

2141

2142

2143

2144

2145

2146

2147

2148

2149

2150

2151

2152

2153

2154

2155

2156

2157

2158

2159

2160

2161

2162

2163

2164

2165

2166

2167

2168

2169

2170

2171

2172

2173

2174

2175

2176

2177

2178

2179

2180

2181

2182

2183

2184

2185

2186

2187

2188

2189

2190

2191

2192

2193

2194

2195

2196

2197

2198

2199

2200

2201

2202

2203

2204

2205

2206

2207

2208

2209

2210

2211

2212

2213

2214

2215

2216

2217

2218

2219

2220

2221

2222

2223

2224

2225

2226

2227

2228

2229

2230

2231

2232

2233

2234

2235

2236

2237

2238

2239

2240

2241

2242

2243

2244

2245

2246

2247

2248

2249

2250

2251

2252

2253

2254

2255

2256

2257

2258

2259

2260

2261

2262

2263

2264

2265

2266

2267

2268

2269

2270

2271

2272

2273

2274

2275

2276

2277

2278

2279

2280

2281

2282

2283

2284

2285

2286

2287

2288

2289

2290

2291

2292

2293

2294

2295

2296

2297

2298

2299

2300

2301

2302

2303

2304

2305

2306

2307

2308

2309

2310

2311

2312

2313

2314

2315

2316

2317

2318

2319

2320

2321

2322

2323

2324

2325

2326

2327

2328

2329

2330

2331

2332

2333

2334

2335

2336

2337

2338

2339

2340

2341

2342

2343

2344

2345

2346

2347

2348

2349

2350

2351

2352

2353

2354

2355

2356

2357

2358

2359

2360

2361

2362

2363

2364

2365

2366

2367

2368

2369

2370

2371

2372

2373

2374

2375

2376

2377

2378

2379

2380

2381

2382

2383

2384

2385

2386

2387

2388

2389

2390

2391

2392

2393

2394

2395

2396

2397

2398

2399

2400

2401

2402

2403

2404

2405

2406

2407

2408

2409

2410

2411

2412

2413

2414

2415

2416

2417

2418

2419

2420

2421

2422

2423

2424

2425

2426

2427

2428

2429

2430

2431

2432

2433

2434

2435

2436

2437

2438

2439

2440

2441

2442

2443

2444

2445

2446

2447

2448

2449

2450

2451

2452

2453

2454

2455

2456

2457

2458

2459

2460

2461

2462

2463

2464

2465

2466

2467

2468

2469

2470

2471

2472

2473

2474

2475

2476

2477

2478

2479

2480

2481

2482

2483

2484

2485

2486

2487

2488

2489

2490

2491

2492

2493

2494

2495

2496

2497

2498

2499

2500

2501

2502

2503

2504

2505

2506

2507

2508

2509

2510

2511

2512

2513

2514

2515

2516

2517

2518

2519

2520

2521

2522

2523

2524

2525

2526

2527

2528

2529

2530

2531

2532

2533

2534

2535

2536

2537

2538

2539

2540

2541

2542

2543

2544

2545

2546

2547

2548

2549

2550

2551

2552

2553

2554

2555

2556

2557

2558

2559

2560

2561

2562

2563

2564

2565

2566

2567

2568

2569

2570

2571

2572

2573

2574

2575

2576

2577

2578

2579

2580

2581

2582

2583

2584

2585

2586

2587

2588

2589

2590

2591

2592

2593

2594

2595

2596

2597

2598

2599

2600

2601

2602

2603

2604

2605

2606

2607

2608

2609

2610

2611

2612

2613

2614

2615

2616

2617

2618

2619

2620

2621

2622

2623

2624

2625

2626

2627

2628

2629

2630

2631

2632

2633

2634

2635

2636

2637

2638

2639

2640

2641

2642

2643

2644

2645

2646

2647

2648

2649

2650

2651

2652

2653

2654

2655

2656

2657

2658

2659

2660

2661

2662

2663

2664

2665

2666

2667

2668

2669

2670

2671

2672

2673

2674

2675

2676

2677

2678

2679

2680

2681

2682

2683

2684

2685

2686

2687

2688

2689

2690

2691

2692

2693

2694

2695

2696

2697

2698

2699

2700

2701

2702

2703

2704

2705

2706

2707

2708

2709

2710

2711

2712

2713

2714

2715

2716

2717

2718

2719

2720

2721

2722

2723

2724

2725

2726

2727

2728

2729

2730

2731

2732

2733

2734

2735

2736

2737

2738

2739

2740

2741

2742

2743

2744

2745

2746

2747

2748

2749

2750

2751

2752

2753

2754

2755

2756

2757

2758

2759

2760

2761

2762

2763

2764

2765

2766

2767

2768

2769

2770

2771

2772

2773

2774

2775

2776

2777

2778

2779

2780

2781

2782

2783

2784

2785

2786

2787

2788

2789

2790

2791

2792

2793

2794

2795

2796

2797

2798

2799

2800

2801

2802

2803

2804

2805

2806

2807

2808

2809

2810

2811

2812

2813

2814

2815

2816

2817

2818

2819

2820

2821

2822

2823

2824

2825

2826

2827

2828

2829

2830

2831

2832

2833

2834

2835

2836

2837

2838

2839

2840

2841

2842

2843

2844

2845

2846

2847

2848

2849

2850

2851

2852

2853

2854

2855

2856

2857

2858

2859

2860

2861

2862

2863

2864

2865

2866

2867

2868

2869

2870

2871

2872

2873

2874

2875

2876

2877

2878

2879

2880

2881

2882

2883

2884

2885

2886

2887

2888

2889

2890

2891

2892

2893

2894

2895

2896

2897

2898

2899

2900

2901

2902

2903

2904

2905

2906

2907

2908

2909

2910

2911

2912

2913

2914

2915

2916

2917

2918

2919

2920

2921

2922

2923

2924

2925

2926

2927

2928

2929

2930

2931

2932

2933

2934

2935

2936

2937

2938

2939

2940

2941

2942

2943

2944

2945

2946

2947

2948

2949

2950

2951

2952

2953

2954

2955

2956

2957

2958

2959

2960

2961

2962

2963

2964

2965

2966

2967

2968

2969

2970

2971

2972

2973

2974

2975

2976

2977

2978

2979

2980

2981

2982

2983

2984

2985

2986

2987

2988

2989

2990

2991

2992

2993

2994

2995

2996

2997

2998

2999

3000

3001

3002

3003

3004

3005

3006

3007

3008

3009

3010

3011

3012

3013

3014

3015

3016

3017

3018

3019

3020

3021

3022

3023

3024

3025

3026

3027

3028

3029

3030

3031

3032

3033

3034

3035

3036

3037

3038

3039

3040

3041

3042

3043

3044

3045

3046

3047

3048

3049

3050

3051

3052

3053

3054

3055

3056

3057

3058

3059

3060

3061

3062

3063

3064

3065

3066

3067

3068

3069

3070

3071

3072

3073

3074

3075

3076

3077

3078

3079

3080

3081

3082

3083

3084

3085

3086

3087

3088

3089

3090

3091

3092

3093

3094

3095

3096

3097

3098

3099

3100

3101

3102

3103

3104

3105

3106

3107

3108

3109

3110

3111

3112

3113

3114

3115

3116

3117

3118

3119

3120

3121

3122

3123

3124

3125

3126

3127

3128

3129

3130

3131

3132

3133

3134

3135

3136

3137

3138

3139

3140

3141

3142

3143

3144

3145

3146

3147

3148

3149

3150

3151

3152

3153

3154

3155

3156

3157

3158

3159

3160

3161

3162

3163

3164

3165

3166

3167

3168

3169

3170

3171

3172

3173

3174

3175

3176

3177

3178

3179

3180

3181

3182

3183

3184

3185

3186

3187

3188

3189

3190

3191

3192

3193

3194

3195

3196

3197

3198

3199

3200

3201

3202

3203

3204

3205

3206

3207

3208

3209

3210

3211

3212

3213

3214

3215

3216

3217

3218

3219

3220

3221

3222

3223

3224

3225

3226

3227

3228

3229

3230

3231

3232

3233

3234

3235

3236

3237

3238

3239

3240

3241

3242

3243

3244

3245

3246

3247

3248

3249

3250

3251

3252

3253

3254

3255

3256

3257

3258

3259

3260

3261

3262

3263

3264

3265

3266

3267

3268

3269

3270

3271

3272

3273

3274

3275

3276

3277

3278

3279

3280

3281

3282

3283

3284

3285

3286

3287

3288

3289

3290

3291

3292

3293

3294

3295

3296

3297

3298

3299

3300

3301

3302

3303

3304

3305

3306

3307

3308

3309

3310

3311

3312

3313

3314

3315

3316

3317

3318

3319

3320

3321

3322

3323

3324

3325

3326

3327

3328

3329

3330

3331

3332

3333

3334

3335

3336

3337

3338

3339

3340

3341

3342

3343

3344

3345

3346

3347

3348

3349

3350

3351

3352

3353

3354

3355

3356

3357

3358

3359

3360

3361

3362

3363

3364

3365

3366

3367

3368

3369

3370

3371

3372

3373

3374

3375

3376

3377

3378

3379

3380

3381

3382

3383

3384

3385

3386

3387

3388

3389

3390

3391

3392

3393

3394

3395

3396

3397

3398

3399

3400

3401

3402

3403

3404

3405

3406

3407

3408

3409

3410

3411

3412

3413

3414

3415

3416

3417

3418

3419

3420

3421

3422

3423

3424

3425

3426

3427

3428

3429

3430

3431

3432

3433

3434

3435

3436

3437

3438

3439

3440

3441

3442

3443

3444

3445

3446

3447

3448

3449

3450

3451

3452

3453

3454

3455

3456

3457

3458

3459

3460

3461

3462

3463

3464

3465

3466

3467

3468

3469

3470

3471

3472

3473

3474

3475

3476

3477

3478

3479

3480

3481

3482

3483

3484

3485

3486

3487

3488

3489

3490

3491

3492

3493

3494

3495

3496

3497

3498

3499

3500

3501

3502

3503

3504

3505

3506

3507

3508

3509

3510

3511

3512

3513

3514

3515

3516

3517

3518

3519

3520

3521

3522

3523

3524

3525

3526

3527

3528

3529

3530

3531

3532

3533

3534

3535

3536

3537

3538

3539

3540

3541

3542

3543

3544

3545

3546

3547

3548

3549

3550

3551

3552

3553

3554

3555

3556

3557

3558

3559

3560

3561

3562

3563

3564

3565

3566

3567

3568

3569

3570

3571

3572

3573

3574

3575

3576

3577

3578

3579

3580

3581

3582

3583

3584

3585

3586

3587

3588

3589

3590

3591

3592

3593

3594

3595

3596

3597

3598

3599

3600

3601

3602

3603

3604

3605

3606

3607

3608

3609

3610

3611

3612

3613

3614

3615

3616

3617

3618

3619

3620

3621

3622

3623

3624

3625

3626

3627

3628

3629

3630

3631

3632

3633

3634

3635

3636

3637

3638

3639

3640

3641

3642

3643

3644

3645

3646

3647

3648

3649

3650

3651

3652

3653

3654

3655

3656

3657

3658

3659

3660

3661

3662

3663

3664

3665

3666

3667

3668

3669

3670

3671

3672

3673

3674

3675

3676

3677

3678

3679

3680

3681

3682

3683

3684

3685

3686

3687

3688

3689

3690

3691

3692

3693

3694

3695

3696

3697

3698

3699

3700

3701

3702

3703

3704

3705

3706

3707

3708

3709

3710

3711

3712

3713

3714

3715

3716

3717

3718

3719

3720

3721

3722

3723

3724

3725

3726

3727

3728

3729

3730

3731

3732

3733

3734

3735

3736

3737

3738

3739

3740

3741

3742

3743

3744

3745

3746

3747

3748

3749

3750

3751

3752

3753

3754

3755

3756

3757

3758

3759

3760

3761

3762

3763

3764

3765

3766

3767

3768

3769

3770

3771

3772

3773

3774

3775

3776

3777

3778

3779

3780

3781

3782

3783

3784

3785

3786

3787

3788

3789

3790

3791

3792

3793

3794

3795

3796

3797

3798

3799

3800

3801

3802

3803

3804

3805

3806

3807

3808

3809

3810

3811

3812

3813

3814

3815

3816

3817

3818

3819

3820

3821

3822

3823

3824

3825

3826

3827

3828

3829

3830

3831

3832

3833

3834

3835

3836

3837

3838

3839

3840

3841

3842

3843

3844

3845

3846

3847

3848

3849

3850

3851

3852

3853

3854

3855

3856

3857

3858

3859

3860

3861

3862

3863

3864

3865

3866

3867

3868

3869

3870

3871

3872

3873

3874

3875

3876

3877

3878

3879

3880

3881

3882

3883

3884

3885

3886

3887

3888

3889

3890

3891

3892

3893

3894

3895

3896

3897

3898

3899

3900

3901

3902

3903

3904

3905

3906

3907

3908

3909

3910

3911

3912

3913

3914

3915

3916

3917

3918

3919

3920

3921

3922

3923

3924

3925

3926

3927

3928

3929

3930

3931

3932

3933

3934

3935

3936

3937

3938

3939

3940

3941

3942

3943

3944

3945

3946

3947

3948

3949

3950

3951

3952

3953

3954

3955

3956

3957

3958

3959

3960

3961

3962

3963

3964

3965

3966

3967

3968

3969

3970

3971

3972

3973

3974

3975

3976

3977

3978

3979

3980

3981

3982

3983

3984

3985

3986

3987

3988

3989

3990

3991

3992

3993

3994

3995

3996

3997

3998

3999

4000

4001

4002

4003

4004

4005

4006

4007

4008

4009

4010

4011

4012

4013

4014

4015

4016

4017

4018

4019

4020

4021

4022

4023

4024

4025

4026

4027

4028

4029

4030

4031

4032

4033

4034

4035

4036

4037

4038

4039

4040

4041

4042

4043

4044

4045

4046

4047

4048

4049

4050

4051

4052

4053

4054

4055

4056

4057

4058

4059

4060

4061

4062

4063

4064

4065

4066

4067

4068

4069

4070

4071

4072

4073

4074

4075

4076

4077

4078

4079

4080

4081

4082

4083

4084

4085

4086

4087

4088

4089

4090

4091

4092

4093

4094

4095

4096

4097

4098

4099

4100

4101

4102

4103

4104

4105

4106

4107

4108

4109

4110

4111

4112

4113

4114

4115

4116

4117

4118

4119

4120

4121

4122

4123

4124

4125

4126

4127

4128

4129

4130

4131

4132

4133

4134

4135

4136

4137

4138

4139

4140

4141

4142

4143

4144

4145

4146

4147

4148

4149

4150

4151

4152

4153

4154

4155

4156

4157

4158

4159

4160

4161

4162

4163

4164

4165

4166

4167

4168

4169

4170

4171

4172

4173

4174

4175

4176

4177

4178

4179

4180

4181

4182

4183

4184

4185

4186

4187

4188

4189

4190

4191

4192

4193

4194

4195

4196

4197

4198

4199

4200

4201

4202

4203

4204

4205

4206

4207

4208

4209

4210

4211

4212

4213

4214

4215

4216

4217

4218

4219

4220

4221

4222

4223

4224

4225

4226

4227

4228

4229

4230

4231

4232

4233

4234

4235

4236

4237

4238

4239

4240

4241

4242

4243

4244

4245

4246

4247

4248

4249

4250

4251

4252

4253

4254

4255

4256

4257

4258

4259

4260

4261

4262

4263

4264

4265

4266

4267

4268

4269

4270

4271

4272

4273

4274

4275

4276

4277

4278

4279

4280

4281

4282

4283

4284

4285

4286

4287

4288

4289

4290

4291

4292

4293

4294

4295

4296

4297

4298

4299

4300

4301

4302

4303

4304

4305

4306

4307

4308

4309

4310

4311

4312

4313

4314

4315

4316

4317

4318

4319

4320

4321

4322

4323

4324

4325

4326

4327

4328

4329

4330

4331

4332

4333

4334

4335

4336

4337

4338

4339

4340

4341

4342

4343

4344

4345

4346

4347

4348

4349

4350

4351

4352

4353

4354

4355

4356

4357

4358

4359

4360

4361

4362

4363

4364

4365

4366

4367

4368

4369

4370

4371

4372

4373

4374

4375

4376

4377

4378

4379

4380

4381

4382

4383

4384

4385

4386

4387

4388

4389

4390

4391

4392

4393

4394

4395

4396

4397

4398

4399

4400

4401

4402

4403

4404

4405

4406

4407

4408

4409

4410

4411

4412

4413

4414

4415

4416

4417

4418

4419

4420

4421

4422

4423

4424

4425

4426

4427

4428

4429

4430

4431

4432

4433

4434

4435

4436

4437

4438

4439

4440

4441

4442

4443

4444

4445

4446

4447

4448

4449

4450

4451

4452

4453

4454

4455

4456

4457

4458

4459

4460

4461

4462

4463

4464

4465

4466

4467

4468

4469

4470

4471

4472

4473

4474

4475

4476

4477

4478

4479

4480

4481

4482

4483

4484

4485

4486

4487

4488

4489

4490

4491

4492

4493

4494

4495

4496

4497

4498

4499

4500

4501

4502

4503

4504

4505

4506

4507

4508

4509

4510

4511

4512

4513

4514

4515

4516

4517

4518

4519

4520

4521

4522

4523

4524

4525

4526

4527

4528

4529

4530

4531

4532

4533

4534

4535

4536

4537

4538

4539

4540

4541

4542

4543

4544

4545

4546

4547

4548

4549

4550

4551

4552

4553

4554

4555

4556

4557

4558

4559

4560

4561

4562

4563

4564

4565

4566

4567

4568

4569

4570

4571

4572

4573

4574

4575

4576

4577

4578

4579

4580

4581

4582

4583

4584

4585

4586

4587

4588

4589

4590

4591

4592

4593

4594

4595

4596

4597

4598

4599

4600

4601

4602

4603

4604

4605

4606

4607

4608

4609

4610

4611

4612

4613

4614

4615

4616

4617

4618

4619

4620

4621

4622

4623

4624

4625

4626

4627

4628

4629

4630

4631

4632

4633

4634

4635

4636

4637

4638

4639

4640

4641

4642

4643

4644

4645

4646

4647

4648

4649

4650

4651

4652

4653

4654

4655

4656

4657

4658

4659

4660

4661

4662

4663

4664

4665

4666

4667

4668

4669

4670

4671

4672

4673

4674

4675

4676

4677

4678

4679

4680

4681

4682

4683

4684

4685

4686

4687

4688

4689

4690

4691

4692

4693

4694

4695

4696

4697

4698

4699

4700

4701

4702

4703

4704

4705

4706

4707

4708

4709

4710

4711

4712

4713

4714

4715

4716

4717

4718

4719

4720

4721

4722

4723

4724

4725

4726

4727

4728

4729

4730

4731

4732

4733

4734

4735

4736

4737

4738

4739

4740

4741

4742

4743

4744

4745

4746

4747

4748

4749

4750

4751

4752

4753

4754

4755

4756

4757

4758

4759

4760

4761

4762

4763

4764

4765

4766

4767

4768

4769

4770

4771

4772

4773

4774

4775

4776

4777

4778

4779

4780

4781

4782

4783

4784

4785

4786

4787

4788

4789

4790

4791

4792

4793

4794

4795

4796

4797

4798

4799

4800

4801

4802

4803

4804

4805

4806

4807

4808

4809

4810

4811

4812

4813

4814

4815

4816

4817

4818

4819

4820

4821

4822

4823

4824

4825

4826

4827

4828

4829

4830

4831

4832

4833

4834

4835

4836

4837

4838

4839

4840

4841

4842

4843

4844

4845

4846

4847

4848

4849

4850

4851

4852

4853

4854

4855

4856

4857

4858

4859

4860

4861

4862

4863

4864

4865

4866

4867

4868

4869

4870

4871

4872

4873

4874

4875

4876

4877

4878

4879

4880

4881

4882

4883

4884

4885

4886

4887

4888

4889

4890

4891

4892

4893

4894

4895

4896

4897

4898

4899

4900

4901

4902

4903

4904

4905

4906

4907

4908

4909

4910

4911

4912

4913

4914

4915

4916

4917

4918

4919

4920

4921

4922

4923

4924

4925

4926

4927

4928

4929

4930

4931

4932

4933

4934

4935

4936

4937

4938

4939

4940

4941

4942

4943

4944

4945

4946

4947

4948

4949

4950

4951

4952

4953

4954

4955

4956

4957

4958

4959

4960

4961

4962

4963

4964

4965

4966

4967

4968

4969

4970

4971

4972

4973

4974

4975

4976

4977

4978

4979

4980

4981

4982

4983

4984

4985

4986

4987

4988

4989

4990

4991

4992

4993

4994

4995

4996

4997

4998

4999

5000

5001

5002

5003

5004

5005

5006

5007

5008

5009

5010

5011

5012

5013

5014

5015

5016

5017

5018

5019

5020

5021

5022

5023

5024

5025

5026

5027

5028

5029

5030

5031

5032

5033

5034

5035

5036

5037

5038

5039

5040

5041

5042

5043

5044

5045

5046

5047

5048

5049

5050

5051

5052

5053

5054

5055

5056

5057

5058

5059

5060

5061

5062

5063

5064

5065

5066

5067

5068

5069

5070

5071

5072

5073

5074

5075

5076

5077

5078

5079

5080

5081

5082

5083

5084

5085

5086

5087

5088

5089

5090

5091

5092

5093

5094

5095

5096

5097

5098

5099

5100

5101

5102

5103

5104

5105

5106

5107

5108

5109

5110

5111

5112

5113

5114

5115

5116

5117

5118

5119

5120

5121

5122

5123

5124

5125

5126

5127

5128

5129

5130

5131

5132

5133

5134

5135

5136

5137

5138

5139

5140

5141

5142

5143

5144

5145

5146

5147

5148

5149

5150

5151

5152

5153

5154

5155

5156

5157

5158

5159

5160

5161

5162

5163

5164

5165

5166

5167

5168

5169

5170

5171

5172

5173

5174

5175

5176

5177

5178

5179

5180

5181

5182

5183

5184

5185

5186

5187

5188

5189

5190

5191

5192

5193

5194

5195

5196

5197

5198

5199

5200

5201

5202

5203

5204

5205

5206

5207

5208

5209

5210

5211

5212

5213

5214

5215

5216

5217

5218

5219

5220

5221

5222

5223

5224

5225

5226

5227

5228

5229

5230

5231

5232

5233

5234

5235

5236

5237

5238

5239

5240

5241

5242

5243

5244

5245

5246

5247

5248

5249

5250

5251

5252

5253

5254

5255

5256

5257

5258

5259

5260

5261

5262

5263

5264

5265

5266

5267

5268

5269

5270

5271

5272

5273

5274

5275

5276

5277

5278

5279

5280

5281

5282

5283

5284

5285

5286

5287

5288

5289

5290

5291

5292

5293

5294

5295

5296

5297

5298

5299

5300

5301

5302

5303

5304

5305

5306

5307

5308

5309

5310

5311

5312

5313

5314

5315

5316

5317

5318

5319

5320

5321

5322

5323

5324

5325

5326

5327

5328

5329

5330

5331

5332

5333

5334

5335

5336

5337

5338

5339

5340

5341

5342

5343

5344

5345

5346

5347

5348

5349

5350

5351

5352

5353

5354

5355

5356

5357

5358

5359

5360

5361

5362

5363

5364

5365

5366

5367

5368

5369

5370

5371

5372

5373

5374

5375

5376

5377

5378

5379

5380

5381

5382

5383

5384

5385

5386

5387

5388

5389

5390

5391

5392

5393

5394

5395

5396

5397

5398

5399

5400

5401

5402

5403

5404

5405

5406

5407

5408

5409

5410

5411

5412

5413

5414

5415

5416

5417

5418

5419

5420

5421

5422

5423

5424

5425

5426

5427

5428

5429

5430

5431

5432

5433

5434

5435

5436

5437

5438

5439

5440

5441

5442

5443

5444

5445

5446

5447

5448

5449

5450

5451

5452

5453

5454

5455

5456

5457

5458

5459

5460

5461

5462

5463

5464

5465

5466

5467

5468

5469

5470

5471

5472

5473

5474

5475

5476

5477

5478

5479

5480

5481

5482

5483

5484

5485

5486

5487

5488

5489

5490

5491

5492

5493

5494

5495

5496

5497

5498

5499

5500

5501

5502

5503

5504

5505

5506

5507

5508

5509

5510

5511

5512

5513

5514

5515

5516

5517

5518

5519

5520

5521

5522

5523

5524

5525

5526

5527

5528

5529

5530

5531

5532

5533

5534

5535

5536

5537

5538

5539

5540

5541

5542

5543

5544

5545

5546

5547

5548

5549

5550

5551

5552

5553

5554

5555

5556

5557

5558

5559

5560

5561

5562

5563

5564

5565

5566

5567

5568

5569

5570

5571

5572

5573

5574

5575

5576

5577

5578

5579

5580

5581

5582

5583

5584

5585

5586

5587

5588

5589

5590

5591

5592

5593

5594

5595

5596

5597

5598

5599

5600

5601

5602

5603

5604

5605

5606

5607

5608

5609

5610

5611

5612

5613

5614

5615

5616

5617

5618

5619

5620

5621

5622

5623

5624

5625

5626

5627

5628

5629

5630

5631

5632

5633

5634

5635

5636

5637

5638

5639

5640

5641

5642

5643

5644

5645

5646

5647

5648

5649

5650

5651

5652

5653

5654

5655

5656

5657

5658

5659

5660

5661

5662

5663

5664

5665

5666

5667

5668

5669

5670

5671

5672

5673

5674

5675

5676

5677

5678

5679

5680

5681

5682

5683

5684

5685

5686

5687

5688

5689

5690

5691

5692

5693

5694

5695

5696

5697

5698

5699

5700

5701

5702

5703

5704

5705

5706

5707

5708

5709

5710

5711

5712

5713

5714

5715

5716

5717

5718

5719

5720

5721

5722

5723

5724

5725

5726

5727

5728

5729

5730

5731

5732

5733

5734

5735

5736

5737

5738

5739

5740

5741

5742

5743

5744

5745

5746

5747

5748

5749

5750

5751

5752

5753

5754

5755

5756

5757

5758

5759

5760

5761

5762

5763

5764

5765

5766

5767

5768

5769

5770

5771

5772

5773

5774

5775

5776

5777

5778

5779

5780

5781

5782

5783

5784

5785

5786

5787

5788

5789

5790

5791

5792

5793

5794

5795

5796

5797

5798

5799

5800

5801

5802

5803

5804

5805

5806

5807

5808

5809

5810

5811

5812

5813

5814

5815

5816

5817

5818

5819

5820

5821

5822

5823

5824

5825

5826

5827

5828

5829

5830

5831

5832

5833

5834

5835

5836

5837

5838

5839

5840

5841

5842

5843

5844

5845

5846

5847

5848

5849

5850

5851

5852

5853

5854

5855

5856

5857

5858

5859

5860

5861

5862

5863

5864

5865

5866

5867

5868

5869

5870

5871

5872

5873

5874

5875

5876

5877

5878

5879

5880

5881

5882

5883

5884

5885

5886

5887

5888

5889

5890

5891

5892

5893

5894

5895

5896

5897

5898

5899

5900

5901

5902

5903

5904

5905

5906

5907

5908

5909

5910

5911

5912

5913

5914

5915

5916

5917

5918

5919

5920

5921

5922

5923

5924

5925

5926

5927

5928

5929

5930

5931

5932

5933

5934

5935

5936

5937

5938

5939

5940

5941

5942

5943

5944

5945

5946

5947

5948

5949

5950

5951

5952

5953

5954

5955

5956

5957

5958

5959

5960

5961

5962

5963

5964

5965

5966

5967

5968

5969

5970

5971

5972

5973

5974

5975

5976

5977

5978

5979

5980

5981

5982

5983

5984

5985

5986

5987

5988

5989

5990

5991

5992

5993

5994

5995

5996

5997

5998

5999

6000

6001

6002

6003

6004

6005

6006

6007

6008

6009

6010

6011

6012

6013

6014

6015

6016

6017

6018

6019

6020

6021

6022

6023

6024

6025

6026

6027

6028

6029

6030

6031

6032

6033

6034

6035

6036

6037

6038

6039

6040

6041

6042

6043

6044

6045

6046

6047

6048

6049

6050

6051

6052

6053

6054

6055

6056

6057

6058

6059

6060

6061

6062

6063

6064

6065

6066

6067

6068

6069

6070

6071

6072

6073

6074

6075

6076

6077

6078

6079

6080

6081

6082

6083

6084

6085

6086

6087

6088

6089

6090

6091

6092

6093

6094

6095

6096

6097

6098

6099

6100

6101

6102

6103

6104

6105

6106

6107

6108

6109

6110

6111

6112

6113

6114

6115

6116

6117

6118

6119

6120

6121

6122

6123

6124

6125

6126

6127

6128

6129

6130

6131

6132

6133

6134

6135

6136

6137

6138

6139

6140

6141

6142

6143

6144

6145

6146

6147

6148

6149

6150

6151

6152

6153

6154

6155

6156

6157

6158

6159

6160

6161

6162

6163

6164

6165

6166

6167

6168

6169

6170

6171

6172

6173

6174

6175

6176

6177

6178

6179

6180

6181

6182

6183

6184

6185

6186

6187

6188

6189

6190

6191

6192

6193

6194

6195

6196

6197

6198

6199

6200

6201

6202

6203

6204

6205

6206

6207

6208

6209

6210

6211

6212

6213

6214

6215

6216

6217

6218

6219

6220

6221

6222

6223

6224

6225

6226

6227

6228

6229

6230

6231

6232

6233

6234

6235

6236

6237

6238

6239

6240

6241

6242

6243

6244

6245

6246

6247

6248

6249

6250

6251

6252

6253

6254

6255

6256

6257

6258

6259

6260

6261

6262

6263

6264

6265

6266

6267

6268

6269

6270

6271

6272

6273

6274

6275

6276

6277

6278

6279

6280

6281

6282

6283

6284

6285

6286

6287

6288

6289

6290

6291

6292

6293

6294

6295

6296

6297

6298

6299

6300

6301

6302

6303

6304

6305

6306

6307

6308

6309

6310

6311

6312

6313

6314

6315

6316

6317

6318

6319

6320

6321

6322

6323

6324

6325

6326

6327

6328

6329

6330

6331

6332

6333

6334

6335

6336

6337

6338

6339

6340

6341

6342

6343

6344

6345

6346

6347

6348

6349

6350

6351

6352

6353

6354

6355

6356

6357

6358

6359

6360

6361

6362

6363

6364

6365

6366

6367

6368

6369

6370

6371

6372

6373

6374

6375

6376

6377

6378

6379

6380

6381

6382

6383

6384

6385

6386

6387

6388

6389

6390

6391

6392

6393

6394

6395

6396

6397

6398

6399

6400

6401

6402

6403

6404

6405

6406

6407

6408

6409

6410

6411

6412

6413

6414

6415

6416

6417

6418

6419

6420

6421

6422

6423

6424

6425

6426

6427

6428

6429

6430

6431

6432

6433

6434

6435

6436

6437

6438

6439

6440

6441

6442

6443

6444

6445

6446

6447

6448

6449

6450

6451

6452

6453

6454

6455

6456

6457

6458

6459

6460

6461

6462

6463

6464

6465

6466

6467

6468

6469

6470

6471

6472

6473

6474

6475

6476

6477

6478

6479

6480

6481

6482

6483

6484

6485

6486

6487

6488

6489

6490

6491

6492

6493

6494

6495

6496

6497

6498

6499

6500

6501

6502

6503

6504

6505

6506

6507

6508

6509

6510

6511

6512

6513

6514

6515

6516

6517

6518

6519

6520

6521

6522

6523

6524

6525

6526

6527

6528

6529

6530

6531

6532

6533

6534

6535

6536

6537

6538

6539

6540

6541

6542

6543

6544

6545

6546

6547

6548

6549

6550

6551

6552

6553

6554

6555

6556

6557

6558

6559

6560

6561

6562

6563

6564

6565

6566

6567

6568

6569

6570

6571

6572

6573

6574

6575

6576

6577

6578

6579

6580

6581

6582

6583

6584

6585

6586

6587

6588

6589

6590

6591

6592

6593

6594

6595

6596

6597

6598

6599

6600

6601

6602

6603

6604

6605

6606

6607

6608

6609

6610

6611

6612

6613

6614

6615

6616

6617

6618

6619

6620

6621

6622

6623

6624

6625

6626

6627

6628

6629

6630

6631

6632

6633

6634

6635

6636

6637

6638

6639

6640

6641

6642

6643

6644

6645

6646

6647

6648

6649

6650

6651

6652

6653

6654

6655

6656

6657

6658

6659

6660

6661

6662

6663

6664

6665

6666

6667

6668

6669

6670

6671

6672

6673

6674

6675

6676

6677

6678

6679

6680

6681

6682

6683

6684

6685

6686

6687

6688

6689

6690

6691

6692

6693

6694

6695

6696

6697

6698

6699

6700

6701

6702

6703

6704

6705

6706

6707

6708

6709

6710

6711

6712

6713

6714

6715

6716

6717

6718

6719

6720

6721

6722

6723

6724

6725

6726

6727

6728

6729

6730

6731

6732

6733

6734

6735

6736

6737

6738

6739

6740

6741

6742

6743

6744

6745

6746

6747

6748

6749

6750

6751

6752

6753

6754

6755

6756

6757

6758

6759

6760

6761

6762

6763

6764

6765

6766

6767

6768

6769

6770

6771

6772

6773

6774

6775

6776

6777

6778

6779

6780

6781

6782

6783

6784

6785

6786

6787

6788

6789

6790

6791

6792

6793

6794

6795

6796

6797

6798

6799

6800

6801

6802

6803

6804

6805

6806

6807

6808

6809

6810

6811

6812

6813

6814

6815

6816

6817

6818

6819

6820

6821

6822

6823

6824

6825

6826

6827

6828

6829

6830

6831

6832

6833

6834

6835

6836

6837

6838

6839

6840

6841

6842

6843

6844

6845

6846

6847

6848

6849

6850

6851

6852

6853

6854

6855

6856

6857

6858

6859

6860

6861

6862

6863

6864

6865

6866

6867

6868

6869

6870

6871

6872

6873

6874

6875

6876

6877

6878

6879

6880

6881

6882

6883

6884

6885

6886

6887

6888

6889

6890

6891

6892

6893

6894

6895

6896

6897

6898

6899

6900

6901

6902

6903

6904

6905

6906

6907

6908

6909

6910

6911

6912

6913

6914

6915

6916

6917

6918

6919

6920

6921

6922

6923

6924

6925

6926

6927

6928

6929

6930

6931

6932

6933

6934

6935

6936

6937

6938

6939

6940

6941

6942

6943

6944

6945

6946

6947

6948

6949

6950

6951

6952

6953

6954

6955

6956

6957

6958

6959

6960

6961

6962

6963

6964

6965

6966

6967

6968

6969

6970

6971

6972

6973

6974

6975

6976

6977

6978

6979

6980

6981

6982

6983

6984

6985

6986

6987

6988

6989

6990

6991

6992

6993

6994

6995

6996

6997

6998

6999

7000

7001

7002

7003

7004

7005

7006

7007

7008

7009

7010

7011

7012

7013

7014

7015

7016

7017

7018

7019

7020

7021

7022

7023

7024

7025

7026

7027

7028

7029

7030

7031

7032

7033

7034

7035

7036

7037

7038

7039

7040

7041

7042

7043

7044

7045

7046

7047

7048

7049

7050

7051

7052

7053

7054

7055

7056

7057

7058

7059

7060

7061

7062

7063

7064

7065

7066

7067

7068

7069

7070

7071

7072

7073

7074

7075

7076

7077

7078

7079

7080

7081

7082

7083

7084

7085

7086

7087

7088

7089

7090

7091

7092

7093

7094

7095

7096

7097

7098

7099

7100

7101

7102

7103

7104

7105

7106

7107

7108

7109

7110

7111

7112

7113

7114

7115

7116

7117

7118

7119

7120

7121

7122

7123

7124

7125

7126

7127

7128

7129

7130

7131

7132

7133

7134

7135

7136

7137

7138

7139

7140

7141

7142

7143

7144

7145

7146

7147

7148

7149

7150

7151

7152

7153

7154

7155

7156

7157

7158

7159

7160

7161

7162

7163

7164

7165

7166

7167

7168

7169

7170

7171

7172

7173

7174

7175

7176

7177

7178

7179

7180

7181

7182

7183

7184

7185

7186

7187

7188

7189

7190

7191

7192

7193

7194

7195

7196

7197

7198

7199

7200

7201

7202

7203

7204

7205

7206

7207

7208

7209

7210

7211

7212

7213

7214

7215

7216

7217

7218

7219

7220

7221

7222

7223

7224

7225

7226

7227

7228

7229

7230

7231

7232

7233

7234

7235

7236

7237

7238

7239

7240

7241

7242

7243

7244

7245

7246

7247

7248

7249

7250

7251

7252

7253

7254

7255

7256

7257

7258

7259

7260

7261

7262

7263

7264

7265

7266

7267

7268

7269

7270

7271

7272

7273

7274

7275

7276

7277

7278

7279

7280

7281

7282

7283

7284

7285

7286

7287

7288

7289

7290

7291

7292

7293

7294

7295

7296

7297

7298

7299

7300

7301

7302

7303

7304

7305

7306

7307

7308

7309

7310

7311

7312

7313

7314

7315

7316

7317

7318

7319

7320

7321

7322

7323

7324

7325

7326

7327

7328

7329

7330

7331

7332

7333

7334

7335

7336

7337

7338

7339

7340

7341

7342

7343

7344

7345

7346

7347

7348

7349

7350

7351

7352

7353

7354

7355

7356

7357

7358

7359

7360

7361

7362

7363

7364

7365

7366

7367

7368

7369

7370

7371

7372

7373

7374

7375

7376

7377

7378

7379

7380

7381

7382

7383

7384

7385

7386

7387

7388

7389

7390

7391

7392

7393

7394

7395

7396

7397

7398

7399

7400

7401

7402

7403

7404

7405

7406

7407

7408

7409

7410

7411

7412

7413

7414

7415

7416

7417

7418

7419

7420

7421

7422

7423

7424

7425

7426

7427

7428

7429

7430

7431

7432

7433

7434

7435

7436

7437

7438

7439

7440

7441

7442

7443

7444

7445

7446

7447

7448

7449

7450

7451

7452

7453

7454

7455

7456

7457

7458

7459

7460

7461

7462

7463

7464

7465

7466

7467

7468

7469

7470

7471

7472

7473

7474

7475

7476

7477

7478

7479

7480

7481

7482

7483

7484

7485

7486

7487

7488

7489

7490

7491

7492

7493

7494

7495

7496

7497

7498

7499

7500

7501

7502

7503

7504

7505

7506

7507

7508

7509

7510

7511

7512

7513

7514

7515

7516

7517

7518

7519

7520

7521

7522

7523

7524

7525

7526

7527

7528

7529

7530

7531

7532

7533

7534

7535

7536

7537

7538

7539

7540

7541

7542

7543

7544

7545

7546

7547

7548

7549

7550

7551

7552

7553

7554

7555

7556

7557

7558

7559

7560

7561

7562

7563

7564

7565

7566

7567

7568

7569

7570

7571

7572

7573

7574

7575

7576

7577

7578

7579

7580

7581

7582

7583

7584

7585

7586

7587

7588

7589

7590

7591

7592

7593

7594

7595

7596

7597

7598

7599

7600

7601

7602

7603

7604

7605

7606

7607

7608

7609

7610

7611

7612

7613

7614

7615

7616

7617

7618

7619

7620

7621

7622

7623

7624

7625

7626

7627

7628

7629

7630

7631

7632

7633

7634

7635

7636

7637

7638

7639

7640

7641

7642

7643

7644

7645

7646

7647

7648

7649

7650

7651

7652

7653

7654

7655

7656

7657

7658

7659

7660

7661

7662

7663

7664

7665

7666

7667

7668

7669

7670

7671

7672

7673

7674

7675

7676

7677

7678

7679

7680

7681

7682

7683

7684

7685

7686

7687

7688

7689

7690

7691

7692

7693

7694

7695

7696

7697

7698

7699

7700

7701

7702

7703

7704

7705

7706

7707

7708

7709

7710

7711

7712

7713

7714

7715

7716

7717

7718

7719

7720

7721

7722

7723

7724

7725

7726

7727

7728

7729

7730

7731

7732

7733

7734

7735

7736

7737

7738

7739

7740

7741

7742

7743

7744

7745

7746

7747

7748

7749

7750

7751

7752

7753

7754

7755

7756

7757

7758

7759

7760

7761

7762

7763

7764

7765

7766

7767

7768

7769

7770

7771

7772

7773

7774

7775

7776

7777

7778

7779

7780

7781

7782

7783

7784

7785

7786

7787

7788

7789

7790

7791

7792

7793

7794

7795

7796

7797

7798

7799

7800

7801

7802

7803

7804

7805

7806

7807

7808

7809

7810

7811

7812

7813

7814

7815

7816

7817

7818

7819

7820

7821

7822

7823

7824

7825

7826

7827

7828

7829

7830

7831

7832

7833

7834

7835

7836

7837

7838

7839

7840

7841

7842

7843

7844

7845

7846

7847

7848

7849

7850

7851

7852

7853

7854

7855

7856

7857

7858

7859

7860

7861

7862

7863

7864

7865

7866

7867

7868

7869

7870

7871

7872

7873

7874

7875

7876

7877

7878

7879

7880

7881

7882

7883

7884

7885

7886

7887

7888

7889

7890

7891

7892

7893

7894

7895

7896

7897

7898

7899

7900

7901

7902

7903

7904

7905

7906

7907

7908

7909

7910

7911

7912

7913

7914

7915

7916

7917

7918

7919

7920

7921

7922

7923

7924

7925

7926

7927

7928

7929

7930

7931

7932

7933

7934

7935

7936

7937

7938

7939

7940

7941

7942

7943

7944

7945

7946

7947

7948

7949

7950

7951

7952

7953

7954

7955

7956

7957

7958

7959

7960

7961

7962

7963

7964

7965

7966

7967

7968

7969

7970

7971

7972

7973

7974

7975

7976

7977

7978

7979

7980

7981

7982

7983

7984

7985

7986

7987

7988

7989

7990

7991

7992

7993

7994

7995

7996

7997

7998

7999

8000

8001

8002

8003

8004

8005

8006

8007

8008

8009

8010

8011

8012

8013

8014

8015

8016

8017

8018

8019

8020

8021

8022

8023

8024

8025

8026

8027

8028

8029

8030

8031

8032

8033

8034

8035

8036

8037

8038

8039

8040

8041

8042

8043

8044

8045

8046

8047

8048

8049

8050

8051

8052

8053

8054

8055

8056

8057

8058

8059

8060

8061

8062

8063

8064

8065

8066

8067

8068

8069

8070

8071

8072

8073

8074

8075

8076

8077

8078

8079

8080

8081

8082

8083

8084

8085

8086

8087

8088

8089

8090

8091

8092

8093

8094

8095

8096

8097

8098

8099

8100

8101

8102

8103

8104

8105

8106

8107

8108

8109

8110

8111

8112

8113

8114

8115

8116

8117

8118

8119

8120

8121

8122

8123

8124

8125

8126

8127

8128

8129

8130

8131

8132

8133

8134

8135

8136

8137

8138

8139

8140

8141

8142

8143

8144

8145

8146

8147

8148

8149

8150

8151

8152

8153

8154

8155

8156

8157

8158

8159

8160

8161

8162

8163

8164

8165

8166

8167

8168

8169

8170

8171

8172

8173

8174

8175

8176

8177

8178

8179

8180

8181

8182

8183

8184

8185

8186

8187

8188

8189

8190

8191

8192

8193

8194

8195

8196

8197

8198

8199

8200

8201

8202

8203

8204

8205

8206

8207

8208

8209

8210

8211

8212

8213

8214

8215

8216

8217

8218

8219

8220

8221

8222

8223

8224

8225

8226

8227

8228

8229

8230

8231

8232

8233

8234

8235

8236

8237

8238

8239

8240

8241

8242

8243

8244

8245

8246

8247

8248

8249

8250

8251

8252

8253

8254

8255

8256

8257

8258

8259

8260

8261

8262

8263

8264

8265

8266

8267

8268

8269

8270

8271

8272

8273

8274

8275

8276

8277

8278

8279

8280

8281

8282

8283

8284

8285

8286

8287

8288

8289

8290

8291

8292

8293

8294

8295

8296

8297

8298

8299

8300

8301

8302

8303

8304

8305

8306

8307

8308

8309

8310

8311

8312

8313

8314

8315

8316

8317

8318

8319

8320

8321

8322

8323

8324

8325

8326

8327

8328

8329

8330

8331

8332

8333

8334

8335

8336

8337

8338

8339

8340

8341

8342

8343

8344

8345

8346

8347

8348

8349

8350

8351

8352

8353

8354

8355

8356

8357

8358

8359

8360

8361

8362

8363

8364

8365

8366

8367

8368

8369

8370

8371

8372

8373

8374

8375

8376

8377

8378

8379

8380

8381

8382

8383

8384

8385

8386

8387

8388

8389

8390

8391

8392

8393

8394

8395

8396

8397

8398

8399

8400

8401

8402

8403

8404

8405

8406

8407

8408

8409

8410

8411

8412

8413

8414

8415

8416

8417

8418

8419

8420

8421

8422

8423

8424

8425

8426

8427

8428

8429

8430

8431

8432

8433

8434

8435

8436

8437

8438

8439

8440

8441

8442

8443

8444

8445

8446

8447

8448

8449

8450

8451

8452

8453

8454

8455

8456

8457

8458

8459

8460

8461

8462

8463

8464

8465

8466

8467

8468

8469

8470

8471

8472

8473

8474

8475

8476

8477

8478

8479

8480

8481

8482

8483

8484

8485

8486

8487

8488

8489

8490

8491

8492

8493

8494

8495

8496

8497

8498

8499

8500

8501

8502

8503

8504

8505

8506

8507

8508

8509

8510

8511

8512

8513

8514

8515

8516

8517

8518

8519

8520

8521

8522

8523

8524

8525

8526

8527

8528

8529

8530

8531

8532

8533

8534

8535

8536

8537

8538

8539

8540

8541

8542

8543

8544

8545

8546

8547

8548

8549

8550

8551

8552

8553

8554

8555

8556

8557

8558

8559

8560

8561

8562

8563

8564

8565

8566

8567

8568

8569

8570

8571

8572

8573

8574

8575

8576

8577

8578

8579

8580

8581

8582

8583

8584

8585

8586

8587

8588

8589

8590

8591

8592

8593

8594

8595

8596

8597

8598

8599

8600

8601

8602

8603

8604

8605

8606

8607

8608

8609

8610

8611

8612

8613

8614

8615

8616

8617

8618

8619

8620

8621

8622

8623

8624

8625

8626

8627

8628

8629

8630

8631

8632

8633

8634

8635

8636

8637

8638

8639

8640

8641

8642

8643

8644

8645

8646

8647

8648

8649

8650

8651

8652

8653

8654

8655

8656

8657

8658

8659

8660

8661

8662

8663

8664

8665

8666

8667

8668

8669

8670

8671

8672

8673

8674

8675

8676

8677

8678

8679

8680

8681

8682

8683

8684

8685

8686

8687

8688

8689

8690

8691

8692

8693

8694

8695

8696

8697

8698

8699

8700

8701

8702

8703

8704

8705

8706

8707

8708

8709

8710

8711

8712

8713

8714

8715

8716

8717

8718

8719

8720

8721

8722

8723

8724

8725

8726

8727

8728

8729

8730

8731

8732

8733

8734

8735

8736

8737

8738

8739

8740

8741

8742

8743

8744

8745

8746

8747

8748

8749

8750

8751

8752

8753

8754

8755

8756

8757

8758

8759

8760

8761

8762

8763

8764

8765

8766

8767

8768

8769

8770

8771

8772

8773

8774

8775

8776

8777

8778

8779

8780

8781

8782

8783

8784

8785

8786

8787

8788

8789

8790

8791

8792

8793

8794

8795

8796

8797

8798

8799

8800

8801

8802

8803

8804

8805

8806

8807

8808

8809

8810

8811

8812

8813

8814

8815

8816

8817

8818

8819

8820

8821

8822

8823

8824

8825

8826

8827

8828

8829

8830

8831

8832

8833

8834

8835

8836

8837

8838

8839

8840

8841

8842

8843

8844

8845

8846

8847

8848

8849

8850

8851

8852

8853

8854

8855

8856

8857

8858

8859

8860

8861

8862

8863

8864

8865

8866

8867

8868

8869

8870

8871

8872

8873

8874

8875

8876

8877

8878

8879

8880

8881

8882

8883

8884

8885

8886

8887

8888

8889

8890

8891

8892

8893

8894

8895

8896

8897

8898

8899

8900

8901

8902

8903

8904

8905

8906

8907

8908

8909

8910

8911

8912

8913

8914

8915

8916

8917

8918

8919

8920

8921

8922

8923

8924

8925

8926

8927

8928

8929

8930

8931

8932

8933

8934

8935

8936

8937

8938

8939

8940

8941

8942

8943

8944

8945

8946

8947

8948

8949

8950

8951

8952

8953

8954

8955

8956

8957

8958

8959

8960

8961

8962

8963

8964

8965

8966

8967

8968

8969

8970

8971

8972

8973

8974

8975

8976

8977

8978

8979

8980

8981

8982

8983

8984

8985

8986

8987

8988

8989

8990

8991

8992

8993

8994

8995

8996

8997

8998

8999

9000

9001

9002

9003

9004

9005

9006

9007

9008

9009

9010

9011

9012

9013

9014

9015

9016

9017

9018

9019

9020

9021

9022

9023

9024

9025

9026

9027

9028

9029

9030

9031

9032

9033

9034

9035

9036

9037

9038

9039

9040

9041

9042

9043

9044

9045

9046

9047

9048

9049

9050

9051

9052

9053

9054

9055

9056

9057

9058

9059

9060

9061

9062

9063

9064

9065

9066

9067

9068

9069

9070

9071

9072

9073

9074

9075

9076

9077

9078

9079

9080

9081

9082

9083

9084

9085

9086

9087

9088

9089

9090

9091

9092

9093

9094

9095

9096

9097

9098

9099

9100

9101

9102

9103

9104

9105

9106

9107

9108

9109

9110

9111

9112

9113

9114

9115

9116

9117

9118

9119

9120

9121

9122

9123

9124

9125

9126

9127

9128

9129

9130

9131

9132

9133

9134

9135

9136

9137

9138

9139

9140

9141

9142

9143

9144

9145

9146

9147

9148

9149

9150

9151

9152

9153

9154

9155

9156

9157

9158

9159

9160

9161

9162

9163

9164

9165

9166

9167

9168

9169

9170

9171

9172

9173

9174

9175

9176

9177

9178

9179

9180

9181

9182

9183

9184

9185

9186

9187

9188

9189

9190

9191

9192

9193

9194

9195

9196

9197

9198

9199

9200

9201

9202

9203

9204

9205

9206

9207

9208

9209

9210

9211

9212

9213

9214

9215

9216

9217

9218

9219

9220

9221

9222

9223

9224

9225

9226

9227

9228

9229

9230

9231

9232

9233

9234

9235

9236

9237

9238

9239

9240

9241

9242

9243

9244

9245

9246

9247

9248

9249

9250

9251

9252

9253

9254

9255

9256

9257

9258

9259

9260

9261

9262

9263

9264

9265

9266

9267

9268

9269

9270

9271

9272

9273

9274

9275

9276

9277

9278

9279

9280

9281

9282

9283

9284

9285

9286

9287

9288

9289

9290

9291

9292

9293

9294

9295

9296

9297

9298

9299

9300

9301

9302

9303

9304

9305

9306

9307

9308

9309

9310

9311

9312

9313

9314

9315

9316

9317

9318

9319

9320

9321

9322

9323

9324

9325

9326

9327

9328

9329

9330

9331

9332

9333

9334

9335

9336

9337

9338

9339

9340

9341

9342

9343

9344

9345

9346

9347

9348

9349

9350

9351

9352

9353

9354

9355

9356

9357

9358

9359

9360

9361

9362

9363

9364

9365

9366

9367

9368

9369

9370

9371

9372

9373

9374

9375

9376

9377

9378

9379

9380

9381

9382

9383

9384

9385

9386

9387

9388

9389

9390

9391

9392

9393

9394

9395

9396

9397

9398

9399

9400

9401

9402

9403

9404

9405

9406

9407

9408

9409

9410

9411

9412

9413

9414

9415

9416

9417

9418

9419

9420

9421

9422

9423

9424

9425

9426

9427

9428

9429

9430

9431

9432

9433

9434

9435

9436

9437

9438

9439

9440

9441

9442

9443

9444

9445

9446

9447

9448

9449

9450

9451

9452

9453

9454

9455

9456

9457

9458

9459

9460

9461

9462

9463

9464

9465

9466

9467

9468

9469

9470

9471

9472

9473

9474

9475

9476

9477

9478

9479

9480

9481

9482

9483

9484

9485

9486

9487

9488

9489

9490

9491

9492

9493

9494

9495

9496

9497

9498

9499

9500

9501

9502

9503

9504

9505

9506

9507

9508

9509

9510

9511

9512

9513

9514

9515

9516

9517

9518

9519

9520

9521

9522

9523

9524

9525

9526

9527

9528

9529

9530

9531

9532

9533

9534

9535

9536

9537

9538

9539

9540

9541

9542

9543

9544

9545

9546

9547

9548

9549

9550

9551

9552

9553

9554

9555

9556

9557

9558

9559

9560

9561

9562

9563

9564

9565

9566

9567

9568

9569

9570

9571

9572

9573

9574

9575

9576

9577

9578

9579

9580

9581

9582

9583

9584

9585

9586

9587

9588

9589

9590

9591

9592

9593

9594

9595

9596

9597

9598

9599

9600

9601

9602

9603

9604

9605

9606

9607

9608

9609

9610

9611

9612

9613

9614

9615

9616

9617

9618

9619

9620

9621

9622

9623

9624

9625

9626

9627

9628

9629

9630

9631

9632

9633

9634

9635

9636

9637

9638

9639

9640

9641

9642

9643

9644

9645

9646

9647

9648

9649

9650

9651

9652

9653

9654

9655

9656

9657

9658

9659

9660

9661

9662

9663

9664

9665

9666

9667

9668

9669

9670

9671

9672

9673

9674

9675

9676

9677

9678

9679

9680

9681

9682

9683

9684

9685

9686

9687

9688

9689

9690

9691

9692

9693

9694

9695

9696

9697

9698

9699

9700

9701

9702

9703

9704

9705

9706

9707

9708

9709

9710

9711

9712

9713

9714

9715

9716

9717

9718

9719

9720

9721

9722

9723

9724

9725

9726

9727

9728

9729

9730

9731

9732

9733

9734

9735

9736

9737

9738

9739

9740

9741

9742

9743

9744

9745

9746

9747

9748

9749

9750

9751

9752

9753

9754

9755

9756

9757

9758

9759

9760

9761

9762

9763

9764

9765

9766

9767

9768

9769

9770

9771

9772

9773

9774

9775

9776

9777

9778

9779

9780

9781

9782

9783

9784

9785

9786

9787

9788

9789

9790

9791

9792

9793

9794

9795

9796

9797

9798

9799

9800

9801

9802

9803

9804

9805

9806

9807

9808

9809

9810

9811

9812

9813

9814

9815

9816

9817

9818

9819

9820

9821

9822

9823

9824

9825

9826

9827

9828

9829

9830

9831

9832

9833

9834

9835

9836

9837

9838

9839

9840

9841

9842

9843

9844

9845

9846

9847

9848

9849

9850

9851

9852

9853

9854

9855

9856

9857

9858

9859

9860

9861

9862

9863

9864

9865

9866

9867

9868

9869

9870

9871

9872

9873

9874

9875

9876

9877

9878

9879

9880

9881

9882

9883

9884

9885

9886

9887

9888

9889

9890

9891

9892

9893

9894

9895

9896

9897

9898

9899

9900

9901

9902

9903

9904

9905

9906

9907

9908

9909

9910

9911

9912

9913

9914

9915

9916

9917

9918

9919

9920

9921

9922

9923

9924

9925

9926

9927

9928

9929

9930

9931

9932

9933

9934

9935

9936

9937

9938

9939

9940

9941

9942

9943

9944

9945

9946

9947

9948

9949

9950

9951

9952

9953

9954

9955

9956

9957

9958

9959

9960

9961

9962

9963

9964

9965

9966

9967

9968

9969

9970

9971

9972

9973

9974

9975

9976

9977

9978

9979

9980

9981

9982

9983

9984

9985

9986

9987

9988

9989

9990

9991

9992

9993

9994

9995

9996

9997

9998

9999

10000

10001

10002

10003

10004

10005

10006

10007

10008

10009

10010

10011

10012

10013

10014

10015

10016

10017

10018

10019

10020

10021

10022

10023

10024

10025

10026

10027

10028

10029

10030

10031

10032

10033

10034

10035

10036

10037

10038

10039

10040

10041

10042

10043

10044

10045

10046

10047

10048

10049

10050

10051

10052

10053

10054

10055

10056

10057

10058

10059

10060

10061

10062

10063

10064

10065

10066

10067

10068

10069

10070

10071

10072

10073

10074

10075

10076

10077

10078

10079

10080

10081

10082

10083

10084

10085

10086

10087

10088

10089

10090

10091

10092

10093

10094

10095

10096

10097

10098

10099

10100

10101

10102

10103

10104

10105

10106

10107

10108

10109

10110

10111

10112

10113

10114

10115

10116

10117

10118

10119

10120

10121

10122

10123

10124

10125

10126

10127

10128

10129

10130

10131

10132

10133

10134

10135

10136

10137

10138

10139

10140

10141

10142

10143

10144

10145

10146

10147

10148

10149

10150

10151

10152

10153

10154

10155

10156

10157

10158

10159

10160

10161

10162

10163

10164

10165

10166

10167

10168

10169

10170

10171

10172

10173

10174

10175

10176

10177

10178

10179

10180

10181

10182

10183

10184

10185

10186

10187

10188

10189

10190

10191

10192

10193

10194

10195

10196

10197

10198

10199

10200

10201

10202

10203

10204

10205

10206

10207

10208

10209

10210

10211

10212

10213

10214

10215

10216

10217

10218

10219

10220

10221

10222

10223

10224

10225

10226

10227

10228

10229

10230

10231

10232

10233

10234

10235

10236

10237

10238

10239

10240

10241

10242

10243

10244

10245

10246

10247

10248

10249

10250

10251

10252

10253

10254

10255

10256

10257

10258

10259

10260

10261

10262

10263

10264

10265

10266

10267

10268

10269

10270

10271

10272

10273

10274

10275

10276

10277

10278

10279

10280

10281

10282

10283

10284

10285

10286

10287

10288

10289

10290

10291

10292

10293

10294

10295

10296

10297

10298

10299

10300

10301

10302

10303

10304

10305

10306

10307

10308

10309

10310

10311

10312

10313

10314

10315

10316

10317

10318

10319

10320

10321

10322

10323

10324

10325

10326

10327

10328

10329

10330

10331

10332

10333

10334

10335

10336

10337

10338

10339

10340

10341

10342

10343

10344

10345

10346

10347

10348

10349

10350

10351

10352

10353

10354

10355

10356

10357

10358

10359

10360

10361

10362

10363

10364

10365

10366

10367

10368

10369

10370

10371

10372

10373

10374

10375

10376

10377

10378

10379

10380

10381

10382

10383

10384

10385

10386

10387

10388

10389

10390

10391

10392

10393

10394

10395

10396

10397

10398

10399

10400

10401

10402

10403

10404

10405

10406

10407

10408

10409

10410

10411

10412

10413

10414

10415

10416

10417

10418

10419

10420

10421

10422

10423

10424

10425

10426

10427

10428

10429

10430

10431

10432

10433

10434

10435

10436

10437

10438

10439

10440

10441

10442

10443

10444

10445

10446

10447

10448

10449

10450

10451

10452

10453

10454

10455

10456

10457

10458

10459

10460

10461

10462

10463

10464

10465

10466

10467

10468

10469

10470

10471

10472

10473

10474

10475

10476

10477

10478

10479

10480

10481

10482

10483

10484

10485

10486

10487

10488

10489

10490

10491

10492

10493

10494

10495

10496

10497

10498

10499

10500

10501

10502

10503

10504

10505

10506

10507

10508

10509

10510

10511

10512

10513

10514

10515

10516

10517

10518

10519

10520

10521

10522

10523

10524

10525

10526

10527

10528

10529

10530

10531

10532

10533

10534

10535

10536

10537

10538

10539

10540

10541

10542

10543

10544

10545

10546

10547

10548

10549

10550

10551

10552

10553

10554

10555

10556

10557

10558

10559

10560

10561

10562

10563

10564

10565

10566

10567

10568

10569

10570

10571

10572

10573

10574

10575

10576

10577

10578

10579

10580

10581

10582

10583

10584

10585

10586

10587

10588

10589

10590

10591

10592

10593

10594

10595

10596

10597

10598

10599

10600

10601

10602

10603

10604

10605

10606

10607

10608

10609

10610

10611

10612

10613

10614

10615

10616

10617

10618

10619

10620

10621

10622

10623

10624

10625

10626

10627

10628

10629

10630

10631

10632

10633

10634

10635

10636

10637

10638

10639

10640

10641

10642

10643

10644

10645

10646

10647

10648

10649

10650

10651

10652

10653

10654

10655

10656

10657

10658

10659

10660

10661

10662

10663

10664

10665

10666

10667

10668

10669

10670

10671

10672

10673

10674

10675

10676

10677

10678

10679

10680

10681

10682

10683

10684

10685

10686

10687

10688

10689

10690

10691

10692

10693

10694

10695

10696

10697

10698

10699

10700

10701

10702

10703

10704

10705

10706

10707

10708

10709

10710

10711

10712

10713

10714

10715

10716

10717

10718

10719

10720

10721

10722

10723

10724

10725

10726

10727

10728

10729

10730

10731

10732

10733

10734

10735

10736

10737

10738

10739

10740

10741

10742

10743

10744

10745

10746

10747

10748

10749

10750

10751

10752

10753

10754

10755

10756

10757

10758

10759

10760

10761

10762

10763

10764

10765

10766

10767

10768

10769

10770

10771

10772

10773

10774

10775

10776

10777

10778

10779

10780

10781

10782

10783

10784

10785

10786

10787

10788

10789

10790

10791

10792

10793

10794

10795

10796

10797

10798

10799

10800

10801

10802

10803

10804

10805

10806

10807

10808

10809

10810

10811

10812

10813

10814

10815

10816

10817

10818

10819

10820

10821

10822

10823

10824

10825

10826

10827

10828

10829

10830

10831

10832

10833

10834

10835

10836

10837

10838

10839

10840

10841

10842

10843

10844

10845

10846

10847

10848

10849

10850

10851

10852

10853

10854

10855

10856

10857

10858

10859

10860

10861

10862

10863

10864

10865

10866

10867

10868

10869

10870

10871

10872

10873

10874

10875

10876

10877

10878

10879

10880

10881

10882

10883

10884

10885

10886

10887

10888

10889

10890

10891

10892

10893

10894

10895

10896

10897

10898

10899

10900

10901

10902

10903

10904

10905

10906

10907

10908

10909

10910

10911

10912

10913

10914

10915

10916

10917

10918

10919

10920

10921

10922

10923

10924

10925

10926

10927

10928

10929

10930

10931

10932

10933

10934

10935

10936

10937

10938

10939

10940

10941

10942

10943

10944

10945

10946

10947

10948

10949

10950

10951

10952

10953

10954

10955

10956

10957

10958

10959

10960

10961

10962

10963

10964

10965

10966

10967

10968

10969

10970

10971

10972

10973

10974

10975

10976

10977

10978

10979

10980

10981

10982

10983

10984

10985

10986

10987

10988

10989

10990

10991

10992

10993

10994

10995

10996

10997

10998

10999

11000

11001

11002

11003

11004

11005

11006

11007

11008

11009

11010

11011

11012

11013

11014

11015

11016

11017

11018

11019

11020

11021

11022

11023

11024

11025

11026

11027

11028

11029

11030

11031

11032

11033

11034

11035

11036

11037

11038

11039

11040

11041

11042

11043

11044

11045

11046

11047

11048

11049

11050

11051

11052

11053

11054

11055

11056

11057

11058

11059

11060

11061

11062

11063

11064

11065

11066

11067

11068

11069

11070

11071

11072

11073

11074

11075

11076

11077

11078

11079

11080

11081

11082

11083

11084

11085

11086

11087

11088

11089

11090

11091

11092

11093

11094

11095

11096

11097

11098

11099

11100

11101

11102

11103

11104

11105

11106

11107

11108

11109

11110

11111

11112

11113

11114

11115

11116

11117

11118

11119

11120

11121

11122

11123

11124

11125

11126

11127

11128

11129

11130

11131

11132

11133

11134

11135

11136

11137

11138

11139

11140

11141

11142

11143

11144

11145

11146

11147

11148

11149

11150

11151

11152

11153

11154

11155

11156

11157

11158

11159

11160

11161

11162

11163

11164

11165

11166

11167

11168

11169

11170

11171

11172

11173

11174

11175

11176

11177

11178

11179

11180

11181

11182

11183

11184

11185

11186

11187

11188

11189

11190

11191

11192

11193

11194

11195

11196

11197

11198

11199

11200

11201

11202

11203

11204

11205

11206

11207

11208

11209

11210

11211

11212

11213

11214

11215

11216

11217

11218

11219

11220

11221

11222

11223

11224

11225

11226

11227

11228

11229

11230

11231

11232

11233

11234

11235

11236

11237

11238

11239

11240

11241

11242

11243

11244

11245

11246

11247

11248

11249

11250

11251

11252

11253

11254

11255

11256

11257

11258

11259

11260

11261

11262

11263

11264

11265

11266

11267

11268

11269

11270

11271

11272

11273

11274

11275

11276

11277

11278

11279

11280

11281

11282

11283

11284

11285

11286

11287

11288

11289

11290

11291

11292

11293

11294

11295

11296

11297

11298

11299

11300

11301

11302

11303

11304

11305

11306

11307

11308

11309

11310

11311

11312

11313

11314

11315

11316

11317

11318

11319

11320

11321

11322

11323

11324

11325

11326

11327

11328

11329

11330

11331

11332

11333

11334

11335

11336

11337

11338

11339

11340

11341

11342

11343

11344

11345

11346

11347

11348

11349

11350

11351

11352

11353

11354

11355

11356

11357

11358

11359

11360

11361

11362

11363

11364

11365

11366

11367

11368

11369

11370

11371

11372

11373

11374

11375

11376

11377

11378

11379

11380

11381

11382

11383

11384

11385

11386

11387

11388

11389

11390

11391

11392

11393

11394

11395

11396

11397

11398

11399

11400

11401

11402

11403

11404

11405

11406

11407

11408

11409

11410

11411

11412

11413

11414

11415

11416

11417

11418

11419

11420

11421

11422

11423

11424

11425

11426

11427

11428

11429

11430

11431

11432

11433

11434

11435

11436

11437

11438

11439

11440

11441

11442

11443

11444

11445

11446

11447

11448

11449

11450

11451

11452

11453

11454

11455

11456

11457

11458

11459

11460

11461

11462

11463

11464

11465

11466

11467

11468

11469

11470

11471

11472

11473

11474

11475

11476

11477

11478

11479

11480

11481

11482

11483

11484

11485

11486

11487

11488

11489

11490

11491

11492

11493

11494

11495

11496

11497

11498

11499

11500

11501

11502

11503

11504

11505

11506

11507

11508

11509

11510

11511

11512

11513

11514

11515

11516

11517

11518

11519

11520

11521

11522

11523

11524

11525

11526

11527

11528

11529

11530

11531

11532

11533

11534

11535

11536

11537

11538

11539

11540

11541

11542

11543

11544

11545

11546

11547

11548

11549

11550

11551

11552

11553

11554

11555

11556

11557

11558

11559

11560

11561

11562

11563

11564

11565

11566

11567

11568

11569

11570

11571

11572

11573

11574

11575

11576

11577

11578

11579

11580

11581

11582

11583

11584

11585

11586

11587

11588

11589

11590

11591

11592

11593

11594

11595

11596

11597

11598

11599

11600

11601

11602

11603

11604

11605

11606

11607

11608

11609

11610

11611

11612

11613

11614

11615

11616

11617

11618

11619

11620

11621

11622

11623

11624

11625

11626

11627

11628

11629

11630

11631

11632

11633

11634

11635

11636

11637

11638

11639

11640

11641

11642

11643

11644

11645

11646

11647

11648

11649

11650

11651

11652

11653

11654

11655

11656

11657

11658

11659

11660

11661

11662

11663

11664

11665

11666

11667

11668

11669

11670

11671

11672

11673

11674

11675

11676

11677

11678

11679

11680

11681

11682

11683

11684

11685

11686

11687

11688

11689

11690

11691

11692

11693

11694

11695

11696

11697

11698

11699

11700

11701

11702

11703

11704

11705

11706

11707

11708

11709

11710

11711

11712

11713

11714

11715

11716

11717

11718

11719

11720

11721

11722

11723

11724

11725

11726

11727

11728

11729

11730

11731

11732

11733

11734

11735

11736

11737

11738

11739

11740

11741

11742

11743

11744

11745

11746

11747

11748

11749

11750

11751

11752

11753

11754

11755

11756

11757

11758

11759

11760

11761

11762

11763

11764

11765

11766

11767

11768

11769

11770

11771

11772

11773

11774

11775

11776

11777

11778

11779

11780

11781

11782

11783

11784

11785

11786

11787

11788

11789

11790

11791

11792

11793

11794

11795

11796

11797

11798

11799

11800

11801

11802

11803

11804

11805

11806

11807

11808

11809

11810

11811

11812

11813

11814

11815

11816

11817

11818

11819

11820

11821

11822

11823

11824

11825

11826

11827

11828

11829

11830

11831

11832

11833

11834

11835

11836

11837

11838

11839

11840

11841

11842

11843

11844

11845

11846

11847

11848

11849

11850

11851

11852

11853

11854

11855

11856

11857

11858

11859

11860

11861

11862

11863

11864

11865

11866

11867

11868

11869

11870

11871

11872

11873

11874

11875

11876

11877

11878

11879

11880

11881

11882

11883

11884

11885

11886

11887

11888

11889

11890

11891

11892

11893

11894

11895

11896

11897

11898

11899

11900

11901

11902

11903

11904

11905

11906

11907

11908

11909

11910

11911

11912

11913

11914

11915

11916

11917

11918

11919

11920

11921

11922

11923

11924

11925

11926

11927

11928

11929

11930

11931

11932

11933

11934

11935

11936

11937

11938

11939

11940

11941

11942

11943

11944

11945

11946

11947

11948

11949

11950

11951

11952

11953

11954

11955

11956

11957

11958

11959

11960

11961

11962

11963

11964

11965

11966

11967

11968

11969

11970

11971

11972

11973

11974

11975

11976

11977

11978

11979

11980

11981

11982

11983

11984

11985

11986

11987

11988

11989

11990

11991

11992

11993

11994

11995

11996

11997

11998

11999

12000

12001

12002

12003

12004

12005

12006

12007

12008

12009

12010

12011

12012

12013

12014

12015

12016

12017

12018

12019

12020

12021

12022

12023

12024

12025

12026

12027

12028

12029

12030

12031

12032

12033

12034

12035

12036

12037

12038

12039

12040

12041

12042

12043

12044

12045

12046

12047

12048

12049

12050

12051

12052

12053

12054

12055

12056

12057

12058

12059

12060

12061

12062

12063

12064

12065

12066

12067

12068

12069

12070

12071

12072

12073

12074

12075

12076

12077

12078

12079

12080

12081

12082

12083

12084

12085

12086

12087

12088

12089

12090

12091

12092

12093

12094

12095

12096

12097

12098

12099

12100

12101

12102

12103

12104

12105

12106

12107

12108

12109

12110

12111

12112

12113

12114

12115

12116

12117

12118

12119

12120

12121

12122

12123

12124

12125

12126

12127

12128

12129

12130

12131

12132

12133

12134

12135

12136

12137

12138

12139

12140

12141

12142

12143

12144

12145

12146

12147

12148

12149

12150

12151

12152

12153

12154

12155

12156

12157

12158

12159

12160

12161

12162

12163

12164

12165

12166

12167

12168

12169

12170

12171

12172

12173

12174

12175

12176

12177

12178

12179

12180

12181

12182

12183

12184

12185

12186

12187

12188

12189

12190

12191

12192

12193

12194

12195

12196

12197

12198

12199

12200

12201

12202

12203

12204

12205

12206

12207

12208

12209

12210

12211

12212

12213

12214

12215

12216

12217

12218

12219

12220

12221

12222

12223

12224

12225

12226

12227

12228

12229

12230

12231

12232

12233

12234

12235

12236

12237

12238

12239

12240

12241

12242

12243

12244

12245

12246

12247

12248

12249

12250

12251

12252

12253

12254

12255

12256

12257

12258

12259

12260

12261

12262

12263

12264

12265

12266

12267

12268

12269

12270

12271

12272

12273

12274

12275

12276

12277

12278

12279

12280

12281

12282

12283

12284

12285

12286

12287

12288

12289

12290

12291

12292

12293

12294

12295

12296

12297

12298

12299

12300

12301

12302

12303

12304

12305

12306

12307

12308

12309

12310

12311

12312

12313

12314

12315

12316

12317

12318

12319

12320

12321

12322

12323

12324

12325

12326

12327

12328

12329

12330

12331

12332

12333

12334

12335

12336

12337

12338

12339

12340

12341

12342

12343

12344

12345

12346

12347

12348

12349

12350

12351

12352

12353

12354

12355

12356

12357

12358

12359

12360

12361

12362

12363

12364

12365

12366

12367

12368

12369

12370

12371

12372

12373

12374

12375

12376

12377

12378

12379

12380

12381

12382

12383

12384

12385

12386

12387

12388

12389

12390

12391

12392

12393

12394

12395

12396

12397

12398

12399

12400

12401

12402

12403

12404

12405

12406

12407

12408

12409

12410

12411

12412

12413

12414

12415

12416

12417

12418

12419

12420

12421

12422

12423

12424

12425

12426

12427

12428

12429

12430

12431

12432

12433

12434

12435

12436

12437

12438

12439

12440

12441

12442

12443

12444

12445

12446

12447

12448

12449

12450

12451

12452

12453

12454

12455

12456

12457

12458

12459

12460

12461

12462

12463

12464

12465

12466

12467

12468

12469

12470

12471

12472

12473

12474

12475

12476

12477

12478

12479

12480

12481

12482

12483

12484

12485

12486

12487

12488

12489

12490

12491

12492

12493

12494

12495

12496

12497

12498

12499

12500

12501

12502

12503

12504

12505

12506

12507

12508

12509

12510

12511

12512

12513

12514

12515

12516

12517

12518

12519

12520

12521

12522

12523

12524

12525

12526

12527

12528

12529

12530

12531

12532

12533

12534

12535

12536

12537

12538

12539

12540

12541

12542

12543

12544

12545

12546

12547

12548

12549

12550

12551

12552

12553

12554

12555

12556

12557

12558

12559

12560

12561

12562

12563

12564

12565

12566

12567

12568

12569

12570

12571

12572

12573

12574

12575

12576

12577

12578

12579

12580

12581

12582

12583

12584

12585

12586

12587

12588

12589

12590

12591

12592

12593

12594

12595

12596

12597

12598

12599

12600

12601

12602

12603

12604

12605

12606

12607

12608

12609

12610

12611

12612

12613

12614

12615

12616

12617

12618

12619

12620

12621

12622

12623

12624

12625

12626

12627

12628

12629

12630

12631

12632

12633

12634

12635

12636

12637

12638

12639

12640

12641

12642

12643

12644

12645

12646

12647

12648

12649

12650

12651

12652

12653

12654

12655

12656

12657

12658

12659

12660

12661

12662

12663

12664

12665

12666

12667

12668

12669

12670

12671

12672

12673

12674

12675

12676

12677

12678

12679

12680

12681

12682

12683

12684

12685

12686

12687

12688

12689

12690

12691

12692

12693

12694

12695

12696

12697

12698

12699

12700

12701

12702

12703

12704

12705

12706

12707

12708

12709

12710

12711

12712

12713

12714

12715

12716

12717

12718

12719

12720

12721

12722

12723

12724

12725

12726

12727

12728

12729

12730

12731

12732

12733

12734

12735

12736

12737

12738

12739

12740

12741

12742

12743

12744

12745

12746

12747

12748

12749

12750

12751

12752

12753

12754

12755

12756

12757

12758

12759

12760

12761

12762

12763

12764

12765

12766

12767

12768

12769

12770

12771

12772

12773

12774

12775

12776

12777

12778

12779

12780

12781

12782

12783

12784

12785

12786

12787

12788

12789

12790

12791

12792

12793

12794

12795

12796

12797

12798

12799

12800

12801

12802

12803

12804

12805

12806

12807

12808

12809

12810

12811

12812

12813

12814

12815

12816

12817

12818

12819

12820

12821

12822

12823

12824

12825

12826

12827

12828

12829

12830

12831

12832

12833

12834

12835

12836

12837

12838

12839

12840

12841

12842

12843

12844

12845

12846

12847

12848

12849

12850

12851

12852

12853

12854

12855

12856

12857

12858

12859

12860

12861

12862

12863

12864

12865

12866

12867

12868

12869

12870

12871

12872

12873

12874

12875

12876

12877

12878

12879

12880

12881

12882

12883

12884

12885

12886

12887

12888

12889

12890

12891

12892

12893

12894

12895

12896

12897

12898

12899

12900

12901

12902

12903

12904

12905

12906

12907

12908

12909

12910

12911

12912

12913

12914

12915

12916

12917

12918

12919

12920

12921

12922

12923

12924

12925

12926

12927

12928

12929

12930

12931

12932

12933

12934

12935

12936

12937

12938

12939

12940

12941

12942

12943

12944

12945

12946

12947

12948

12949

12950

12951

12952

12953

12954

12955

12956

12957

12958

12959

12960

12961

12962

12963

12964

12965

12966

12967

12968

12969

12970

12971

12972

12973

12974

12975

12976

12977

12978

12979

12980

12981

12982

12983

12984

12985

12986

12987

12988

12989

12990

12991

12992

12993

12994

12995

12996

12997

12998

12999

13000

13001

13002

13003

13004

13005

13006

13007

13008

13009

13010

13011

13012

13013

13014

13015

13016

13017

13018

13019

13020

13021

13022

13023

13024

13025

13026

13027

13028

13029

13030

13031

13032

13033

13034

13035

13036

13037

13038

13039

13040

13041

13042

13043

13044

13045

13046

13047

13048

13049

13050

13051

13052

13053

13054

13055

13056

13057

13058

13059

13060

13061

13062

13063

13064

13065

13066

13067

13068

13069

13070

13071

13072

13073

13074

13075

13076

13077

13078

13079

13080

13081

13082

13083

13084

13085

13086

13087

13088

13089

13090

13091

13092

13093

13094

13095

13096

13097

13098

13099

13100

13101

13102

13103

13104

13105

13106

13107

13108

13109

13110

13111

13112

13113

13114

13115

13116

13117

13118

13119

13120

13121

13122

13123

13124

13125

13126

13127

13128

13129

13130

13131

13132

13133

13134

13135

13136

13137

13138

13139

13140

13141

13142

13143

13144

13145

13146

13147

13148

13149

13150

13151

13152

13153

13154

13155

13156

13157

13158

13159

13160

13161

13162

13163

13164

13165

13166

13167

13168

13169

13170

13171

13172

13173

13174

13175

13176

13177

13178

13179

13180

13181

13182

13183

13184

13185

13186

13187

13188

13189

13190

13191

13192

13193

13194

13195

13196

13197

13198

13199

13200

13201

13202

13203

13204

13205

13206

13207

13208

13209

13210

13211

13212

13213

13214

13215

13216

13217

13218

13219

13220

13221

13222

13223

13224

13225

13226

13227

13228

13229

13230

13231

13232

13233

13234

13235

13236

13237

13238

13239

13240

13241

13242

13243

13244

13245

13246

13247

13248

13249

13250

13251

13252

13253

13254

13255

13256

13257

13258

13259

13260

13261

13262

13263

13264

13265

13266

13267

13268

13269

13270

13271

13272

13273

13274

13275

13276

13277

13278

13279

13280

13281

13282

13283

13284

13285

13286

13287

13288

13289

13290

13291

13292

13293

13294

13295

13296

13297

13298

13299

13300

13301

13302

13303

13304

13305

13306

13307

13308

13309

13310

13311

13312

13313

13314

13315

13316

13317

13318

13319

13320

13321

13322

13323

13324

13325

13326

13327

13328

13329

13330

13331

13332

13333

13334

13335

13336

13337

13338

13339

13340

13341

13342

13343

13344

13345

13346

13347

13348

13349

13350

13351

13352

13353

13354

13355

13356

13357

13358

13359

13360

13361

13362

13363

13364

13365

13366

13367

13368

13369

13370

13371

13372

13373

13374

13375

13376

13377

13378

13379

13380

13381

13382

13383

13384

13385

13386

13387

13388

13389

13390

13391

13392

13393

13394

13395

13396

13397

13398

13399

13400

13401

13402

13403

13404

13405

13406

13407

13408

13409

13410

13411

13412

13413

13414

13415

13416

13417

13418

13419

13420

13421

13422

13423

13424

13425

13426

13427

13428

13429

13430

13431

13432

13433

13434

13435

13436

13437

13438

13439

13440

13441

13442

13443

13444

13445

13446

13447

13448

13449

13450

13451

13452

13453

13454

13455

13456

13457

13458

13459

13460

13461

13462

13463

13464

13465

13466

13467

13468

13469

13470

13471

13472

13473

13474

13475

13476

13477

13478

13479

13480

13481

13482

13483

13484

13485

13486

13487

13488

13489

13490

13491

13492

13493

13494

13495

13496

13497

13498

13499

13500

13501

13502

13503

13504

13505

13506

13507

13508

13509

13510

13511

13512

13513

13514

13515

13516

13517

13518

13519

13520

13521

13522

13523

13524

13525

13526

13527

13528

13529

13530

13531

13532

13533

13534

13535

13536

13537

13538

13539

13540

13541

13542

13543

13544

13545

13546

13547

13548

13549

13550

13551

13552

13553

13554

13555

13556

13557

13558

13559

13560

13561

13562

13563

13564

13565

13566

13567

13568

13569

13570

13571

13572

13573

13574

13575

13576

13577

13578

13579

13580

13581

13582

13583

13584

13585

13586

13587

13588

13589

13590

13591

13592

13593

13594

13595

13596

13597

13598

13599

13600

13601

13602

13603

13604

13605

13606

13607

13608

13609

13610

13611

13612

13613

13614

13615

13616

13617

13618

13619

13620

13621

13622

13623

13624

13625

13626

13627

13628

13629

13630

13631

13632

13633

13634

13635

13636

13637

13638

13639

13640

13641

13642

13643

13644

13645

13646

13647

13648

13649

13650

13651

13652

13653

13654

13655

13656

13657

13658

13659

13660

13661

13662

13663

13664

13665

13666

13667

13668

13669

13670

13671

13672

13673

13674

13675

13676

13677

13678

13679

13680

13681

13682

13683

13684

13685

13686

13687

13688

13689

13690

13691

13692

13693

13694

13695

13696

13697

13698

13699

13700

13701

13702

13703

13704

13705

13706

13707

13708

13709

13710

13711

13712

13713

13714

13715

13716

13717

13718

13719

13720

13721

13722

13723

13724

13725

13726

13727

13728

13729

13730

13731

13732

13733

13734

13735

13736

13737

13738

13739

13740

13741

13742

13743

13744

13745

13746

13747

13748

13749

13750

13751

13752

13753

13754

13755

13756

13757

13758

13759

13760

13761

13762

13763

13764

13765

13766

13767

13768

13769

13770

13771

13772

13773

13774

13775

13776

13777

13778

13779

13780

13781

13782

13783

13784

13785

13786

13787

13788

13789

13790

13791

13792

13793

13794

13795

13796

13797

13798

13799

13800

13801

13802

13803

13804

13805

13806

13807

13808

13809

13810

13811

13812

13813

13814

13815

13816

13817

13818

13819

13820

13821

13822

13823

13824

13825

13826

13827

13828

13829

13830

13831

13832

13833

13834

13835

13836

13837

13838

13839

13840

13841

13842

13843

13844

13845

13846

13847

13848

13849

13850

13851

13852

13853

13854

13855

13856

13857

13858

13859

13860

13861

13862

13863

13864

13865

13866

13867

13868

13869

13870

13871

13872

13873

13874

13875

13876

13877

13878

13879

13880

13881

13882

13883

13884

13885

13886

13887

13888

13889

13890

13891

13892

13893

13894

13895

13896

13897

13898

13899

13900

13901

13902

13903

13904

13905

13906

13907

13908

13909

13910

13911

13912

13913

13914

13915

13916

13917

13918

13919

13920

13921

13922

13923

13924

13925

13926

13927

13928

13929

13930

13931

13932

13933

13934

13935

13936

13937

13938

13939

13940

13941

13942

13943

13944

13945

13946

13947

13948

13949

13950

13951

13952

13953

13954

13955

13956

13957

13958

13959

13960

13961

13962

13963

13964

13965

13966

13967

13968

13969

13970

13971

13972

13973

13974

13975

13976

13977

13978

13979

13980

13981

13982

13983

13984

13985

13986

13987

13988

13989

13990

13991

13992

13993

13994

13995

13996

13997

13998

13999

14000

14001

14002

14003

14004

14005

14006

14007

14008

14009

14010

14011

14012

14013

14014

14015

14016

14017

14018

14019

14020

14021

14022

14023

14024

14025

14026

14027

14028

14029

14030

14031

14032

14033

14034

14035

14036

14037

14038

14039

14040

14041

14042

14043

14044

14045

14046

14047

14048

14049

14050

14051

14052

14053

14054

14055

14056

14057

14058

14059

14060

14061

14062

14063

14064

14065

14066

14067

14068

14069

14070

14071

14072

14073

14074

14075

14076

14077

14078

14079

14080

14081

14082

14083

14084

14085

14086

14087

14088

14089

14090

14091

14092

14093

14094

14095

14096

14097

14098

14099

14100

14101

14102

14103

14104

14105

14106

14107

14108

14109

14110

14111

14112

14113

14114

14115

14116

14117

14118

14119

14120

14121

14122

14123

14124

14125

14126

14127

14128

14129

14130

14131

14132

14133

14134

14135

14136

14137

14138

14139

14140

14141

14142

14143

14144

14145

14146

14147

14148

14149

14150

14151

14152

14153

14154

14155

14156

14157

14158

14159

14160

14161

14162

14163

14164

14165

14166

14167

14168

14169

14170

14171

14172

14173

14174

14175

14176

14177

14178

14179

14180

14181

14182

14183

14184

14185

14186

14187

14188

14189

14190

14191

14192

14193

14194

14195

14196

14197

14198

14199

14200

14201

14202

14203

14204

14205

14206

14207

14208

14209

14210

14211

14212

14213

14214

14215

14216

14217

14218

14219

14220

14221

14222

14223

14224

14225

14226

14227

14228

14229

14230

14231

14232

14233

14234

14235

14236

14237

14238

14239

14240

14241

14242

14243

14244

14245

14246

14247

14248

14249

14250

14251

14252

14253

14254

14255

14256

14257

14258

14259

14260

14261

14262

14263

14264

14265

14266

14267

14268

14269

14270

14271

14272

14273

14274

14275

14276

14277

14278

14279

14280

14281

14282

14283

14284

14285

14286

14287

14288

14289

14290

14291

14292

14293

14294

14295

14296

14297

14298

14299

14300

14301

14302

14303

14304

14305

14306

14307

14308

14309

14310

14311

14312

14313

14314

14315

14316

14317

14318

14319

14320

14321

14322

14323

14324

14325

14326

14327

14328

14329

14330

14331

14332

14333

14334

14335

14336

14337

14338

14339

14340

14341

14342

14343

14344

14345

14346

14347

14348

14349

14350

14351

14352

14353

14354

14355

14356

14357

14358

14359

14360

14361

14362

14363

14364

14365

14366

14367

14368

14369

14370

14371

14372

14373

14374

14375

14376

14377

14378

14379

14380

14381

14382

14383

14384

14385

14386

14387

14388

14389

14390

14391

14392

14393

14394

14395

14396

14397

14398

14399

14400

14401

14402

14403

14404

14405

14406

14407

14408

14409

14410

14411

14412

14413

14414

14415

14416

14417

14418

14419

14420

14421

14422

14423

14424

14425

14426

14427

14428

14429

14430

14431

14432

14433

14434

14435

14436

14437

14438

14439

14440

14441

14442

14443

14444

14445

14446

14447

14448

14449

14450

14451

14452

14453

14454

14455

14456

14457

14458

14459

14460

14461

14462

14463

14464

14465

14466

14467

14468

14469

14470

14471

14472

14473

14474

14475

14476

14477

14478

14479

14480

14481

14482

14483

14484

14485

14486

14487

14488

14489

14490

14491

14492

14493

14494

14495

14496

14497

14498

14499

14500

14501

14502

14503

14504

14505

14506

14507

14508

14509

14510

14511

14512

14513

14514

14515

14516

14517

14518

14519

14520

14521

14522

14523

14524

14525

14526

14527

14528

14529

14530

14531

14532

14533

14534

14535

14536

14537

14538

14539

14540

14541

14542

14543

14544

14545

14546

14547

14548

14549

14550

14551

14552

14553

14554

14555

14556

14557

14558

14559

14560

14561

14562

14563

14564

14565

14566

14567

14568

14569

14570

14571

14572

14573

14574

14575

14576

14577

14578

14579

14580

14581

14582

14583

14584

14585

14586

14587

14588

14589

14590

14591

14592

14593

14594

14595

14596

14597

14598

14599

14600

14601

14602

14603

14604

14605

14606

14607

14608

14609

14610

14611

14612

14613

14614

14615

14616

14617

14618

14619

14620

14621

14622

14623

14624

14625

14626

14627

14628

14629

14630

14631

14632

14633

14634

14635

14636

14637

14638

14639

14640

14641

14642

14643

14644

14645

14646

14647

14648

14649

14650

14651

14652

14653

14654

14655

14656

14657

14658

14659

14660

14661

14662

14663

14664

14665

14666

14667

14668

14669

14670

14671

14672

14673

14674

14675

14676

14677

14678

14679

14680

14681

14682

14683

14684

14685

14686

14687

14688

14689

14690

14691

14692

14693

14694

14695

14696

14697

14698

14699

14700

14701

14702

14703

14704

14705

14706

14707

14708

14709

14710

14711

14712

14713

14714

14715

14716

14717

14718

14719

14720

14721

14722

14723

14724

14725

14726

14727

14728

14729

14730

14731

14732

14733

14734

14735

14736

14737

14738

14739

14740

14741

14742

14743

14744

14745

14746

14747

14748

14749

14750

14751

14752

14753

14754

14755

14756

14757

14758

14759

14760

14761

14762

14763

14764

14765

14766

14767

14768

14769

14770

14771

14772

14773

14774

14775

14776

14777

14778

14779

14780

14781

14782

14783

14784

14785

14786

14787

14788

14789

14790

14791

14792

14793

14794

14795

14796

14797

14798

14799

14800

14801

14802

14803

14804

14805

14806

14807

14808

14809

14810

14811

14812

14813

14814

14815

14816

14817

14818

14819

14820

14821

14822

14823

14824

14825

14826

14827

14828

14829

14830

14831

14832

14833

14834

14835

14836

14837

14838

14839

14840

14841

14842

14843

14844

14845

14846

14847

14848

14849

14850

14851

14852

14853

14854

14855

14856

14857

14858

14859

14860

14861

14862

14863

14864

14865

14866

14867

14868

14869

14870

14871

14872

14873

14874

14875

14876

14877

14878

14879

14880

14881

14882

14883

14884

14885

14886

14887

14888

14889

14890

14891

14892

14893

14894

14895

14896

14897

14898

14899

14900

14901

14902

14903

14904

14905

14906

14907

14908

14909

14910

14911

14912

14913

14914

14915

14916

14917

14918

14919

14920

14921

14922

14923

14924

14925

14926

14927

14928

14929

14930

14931

14932

14933

14934

14935

14936

14937

14938

14939

14940

14941

14942

14943

14944

14945

14946

14947

14948

14949

14950

14951

14952

14953

14954

14955

14956

14957

14958

14959

14960

14961

14962

14963

14964

14965

14966

14967

14968

14969

14970

14971

14972

14973

14974

14975

14976

14977

14978

14979

14980

14981

14982

14983

14984

14985

14986

14987

14988

14989

14990

14991

14992

14993

14994

14995

14996

14997

14998

14999

15000

15001

15002

15003

15004

15005

15006

15007

15008

15009

15010

15011

15012

15013

15014

15015

15016

15017

15018

15019

15020

15021

15022

15023

15024

15025

15026

15027

15028

15029

15030

15031

15032

15033

15034

15035

15036

15037

15038

15039

15040

15041

15042

15043

15044

15045

15046

15047

15048

15049

15050

15051

15052

15053

15054

15055

15056

15057

15058

15059

15060

15061

15062

15063

15064

15065

15066

15067

15068

15069

15070

15071

15072

15073

15074

15075

15076

15077

15078

15079

15080

15081

15082

15083

15084

15085

15086

15087

15088

15089

15090

15091

15092

15093

15094

15095

15096

15097

15098

15099

15100

15101

15102

15103

15104

15105

15106

15107

15108

15109

15110

15111

15112

15113

15114

15115

15116

15117

15118

15119

15120

15121

15122

15123

15124

15125

15126

15127

15128

15129

15130

15131

15132

15133

15134

15135

15136

15137

15138

15139

15140

15141

15142

15143

15144

15145

15146

15147

15148

15149

15150

15151

15152

15153

15154

15155

15156

15157

15158

15159

15160

15161

15162

15163

15164

15165

15166

15167

15168

15169

15170

15171

15172

15173

15174

15175

15176

15177

15178

15179

15180

15181

15182

15183

15184

15185

15186

15187

15188

15189

15190

15191

15192

15193

15194

15195

15196

15197

15198

15199

15200

15201

15202

15203

15204

15205

15206

15207

15208

15209

15210

15211

15212

15213

15214

15215

15216

15217

15218

15219

15220

15221

15222

15223

15224

15225

15226

15227

15228

15229

15230

15231

15232

15233

15234

15235

15236

15237

15238

15239

15240

15241

15242

15243

15244

15245

15246

15247

15248

15249

15250

15251

15252

15253

15254

r""" 

Base class for matrices, part 2 

  

For design documentation see matrix/docs.py. 

  

AUTHORS: 

  

- William Stein: initial version 

  

- Miguel Marco (2010-06-19): modified eigenvalues and eigenvectors functions to 

allow the option extend=False 

  

- Rob Beezer (2011-02-05): refactored all of the matrix kernel routines 

  

TESTS:: 

  

sage: m = matrix(ZZ['x'], 2, 3, [1..6]) 

sage: TestSuite(m).run() 

  

Check that a pair consisting of a matrix and its echelon form is 

pickled correctly (this used to give a wrong answer due to a Python 

bug, see :trac:`17527`):: 

  

sage: K.<x> = FractionField(QQ['x']) 

sage: m = Matrix([[1], [x]]) 

sage: t = (m, m.echelon_form()) 

sage: loads(dumps(t)) 

( 

[1] [1] 

[x], [0] 

) 

""" 

  

#***************************************************************************** 

# Copyright (C) 2005, 2006 William Stein <wstein@gmail.com> 

# 

# Distributed under the terms of the GNU General Public License (GPL) 

# as published by the Free Software Foundation; either version 2 of 

# the License, or (at your option) any later version. 

# http://www.gnu.org/licenses/ 

#***************************************************************************** 

from __future__ import print_function, absolute_import, division 

  

from cpython cimport * 

from cysignals.signals cimport sig_check 

  

from sage.misc.randstate cimport randstate, current_randstate 

from sage.structure.coerce cimport py_scalar_parent 

from sage.structure.sequence import Sequence 

from sage.structure.element import is_Vector 

from sage.structure.element cimport have_same_parent, coercion_model 

from sage.misc.misc import verbose, get_verbose 

from sage.rings.ring import is_Ring 

from sage.rings.number_field.number_field_base import is_NumberField 

from sage.rings.integer_ring import ZZ, is_IntegerRing 

from sage.rings.integer import Integer 

from sage.rings.rational_field import QQ, is_RationalField 

from sage.rings.real_double import RDF 

from sage.rings.complex_double import CDF 

from sage.rings.real_mpfr import RealField 

from sage.rings.complex_field import ComplexField 

from sage.rings.finite_rings.integer_mod_ring import IntegerModRing 

from sage.misc.derivative import multi_derivative 

from sage.arith.numerical_approx cimport digits_to_bits 

from copy import copy 

  

import sage.modules.free_module 

from . import berlekamp_massey 

from sage.modules.free_module_element import is_FreeModuleElement 

from sage.matrix.matrix_misc import permanental_minor_polynomial 

  

  

cdef class Matrix(Matrix1): 

def _backslash_(self, B): 

r""" 

Used to compute `A \backslash B`, i.e., the backslash solver 

operator. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, 3, [1,2,4,2,3,1,0,1,2]) 

sage: B = matrix(QQ, 3, 2, [1,7,5, 2,1,3]) 

sage: C = A._backslash_(B); C 

[ -1 1] 

[13/5 -3/5] 

[-4/5 9/5] 

sage: A*C == B 

True 

sage: A._backslash_(B) == A \ B 

True 

sage: A._backslash_(B) == A.solve_right(B) 

True 

""" 

return self.solve_right(B) 

  

def subs(self, *args, **kwds): 

""" 

Substitute values to the variables in that matrix. 

  

All the arguments are transmitted unchanged to the method ``subs`` of 

the coefficients. 

  

EXAMPLES:: 

  

sage: var('a,b,d,e') 

(a, b, d, e) 

sage: m = matrix([[a,b], [d,e]]) 

sage: m.substitute(a=1) 

[1 b] 

[d e] 

sage: m.subs(a=b, b=d) 

[b d] 

[d e] 

sage: m.subs({a: 3, b:2, d:1, e:-1}) 

[ 3 2] 

[ 1 -1] 

  

The parent of the newly created matrix might be different from the 

initial one. It depends on what the method ``.subs`` does on 

coefficients (see :trac:`19045`):: 

  

sage: x = polygen(ZZ) 

sage: m = matrix([[x]]) 

sage: m2 = m.subs(x=2) 

sage: m2.parent() 

Full MatrixSpace of 1 by 1 dense matrices over Integer Ring 

sage: m1 = m.subs(x=RDF(1)) 

sage: m1.parent() 

Full MatrixSpace of 1 by 1 dense matrices over Real Double Field 

  

However, sparse matrices remain sparse:: 

  

sage: m = matrix({(3,2): -x, (59,38): x^2+2}, nrows=1000, ncols=1000) 

sage: m1 = m.subs(x=1) 

sage: m1.is_sparse() 

True 

""" 

from sage.matrix.constructor import matrix 

if self.is_sparse(): 

return matrix({ij: self[ij].subs(*args, **kwds) for ij in self.nonzero_positions()}, 

nrows=self._nrows, ncols=self._ncols, sparse=True) 

else: 

return matrix([a.subs(*args, **kwds) for a in self.list()], 

nrows=self._nrows, ncols=self._ncols, sparse=False) 

  

def solve_left(self, B, check=True): 

""" 

If self is a matrix `A`, then this function returns a 

vector or matrix `X` such that `X A = B`. If 

`B` is a vector then `X` is a vector and if 

`B` is a matrix, then `X` is a matrix. 

  

INPUT: 

  

  

- ``B`` - a matrix 

  

- ``check`` - bool (default: True) - if False and self 

is nonsquare, may not raise an error message even if there is no 

solution. This is faster but more dangerous. 

  

  

EXAMPLES:: 

  

sage: A = matrix(QQ,4,2, [0, -1, 1, 0, -2, 2, 1, 0]) 

sage: B = matrix(QQ,2,2, [1, 0, 1, -1]) 

sage: X = A.solve_left(B) 

sage: X*A == B 

True 

  

sage: M = matrix([(3,-1,0,0),(1,1,-2,0),(0,0,0,-3)]) 

sage: B = matrix(QQ,3,1, [0,0,-1]) 

sage: M.solve_left(B) 

Traceback (most recent call last): 

... 

ValueError: number of columns of self must equal number of columns of B 

  

TESTS:: 

  

sage: A = matrix(QQ,4,2, [0, -1, 1, 0, -2, 2, 1, 0]) 

sage: B = vector(QQ,2, [2,1]) 

sage: X = A.solve_left(B) 

sage: X*A == B 

True 

sage: X 

(-1, 2, 0, 0) 

sage: A = Matrix(Zmod(128), 2, 3, [5, 29, 33, 64, 0, 7]) 

sage: B = vector(Zmod(128), [31,39,56]) 

sage: X = A.solve_left(B); X 

(19, 83) 

sage: X * A == B 

True 

  

sage: M = matrix([(3,-1,0,0),(1,1,-2,0),(0,0,0,-3)]) 

sage: B = matrix(QQ,3,1, [0,0,-1]) 

sage: M.solve_left(B) 

Traceback (most recent call last): 

... 

ValueError: number of columns of self must equal number of columns of B 

""" 

if is_Vector(B): 

try: 

return self.transpose().solve_right(B, check=check) 

except ValueError as e: 

raise ValueError(str(e).replace('row', 'column')) 

else: 

try: 

return self.transpose().solve_right(B.transpose(), check=check).transpose() 

except ValueError as e: 

raise ValueError(str(e).replace('row', 'column')) 

  

def solve_right(self, B, check=True): 

r""" 

If self is a matrix `A`, then this function returns a 

vector or matrix `X` such that `A X = B`. If 

`B` is a vector then `X` is a vector and if 

`B` is a matrix, then `X` is a matrix. 

  

.. NOTE:: 

  

In Sage one can also write ``A \backslash B`` for 

``A.solve_right(B)``, i.e., Sage implements the "the 

MATLAB/Octave backslash operator". 

  

INPUT: 

  

  

- ``B`` - a matrix or vector 

  

- ``check`` - bool (default: True) - if False and self 

is nonsquare, may not raise an error message even if there is no 

solution. This is faster but more dangerous. 

  

  

OUTPUT: a matrix or vector 

  

.. SEEALSO:: 

  

:meth:`solve_left` 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, 3, [1,2,3,-1,2,5,2,3,1]) 

sage: b = vector(QQ,[1,2,3]) 

sage: x = A \ b; x 

(-13/12, 23/12, -7/12) 

sage: A * x 

(1, 2, 3) 

  

We solve with A nonsquare:: 

  

sage: A = matrix(QQ,2,4, [0, -1, 1, 0, -2, 2, 1, 0]); B = matrix(QQ,2,2, [1, 0, 1, -1]) 

sage: X = A.solve_right(B); X 

[-3/2 1/2] 

[ -1 0] 

[ 0 0] 

[ 0 0] 

sage: A*X == B 

True 

  

Another nonsingular example:: 

  

sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); v = vector([-1/2,-1]) 

sage: x = A \ v; x 

(-1/2, 0, 0) 

sage: A*x == v 

True 

  

Same example but over `\ZZ`:: 

  

sage: A = matrix(ZZ,2,3, [1,2,3,2,4,6]); v = vector([-1,-2]) 

sage: A \ v 

(-1, 0, 0) 

  

An example in which there is no solution:: 

  

sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); v = vector([1,1]) 

sage: A \ v 

Traceback (most recent call last): 

... 

ValueError: matrix equation has no solutions 

  

A ValueError is raised if the input is invalid:: 

  

sage: A = matrix(QQ,4,2, [0, -1, 1, 0, -2, 2, 1, 0]) 

sage: B = matrix(QQ,2,2, [1, 0, 1, -1]) 

sage: X = A.solve_right(B) 

Traceback (most recent call last): 

... 

ValueError: number of rows of self must equal number of rows of B 

  

We solve with A singular:: 

  

sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); B = matrix(QQ,2,2, [6, -6, 12, -12]) 

sage: X = A.solve_right(B); X 

[ 6 -6] 

[ 0 0] 

[ 0 0] 

sage: A*X == B 

True 

  

We illustrate left associativity, etc., of the backslash operator. 

  

:: 

  

sage: A = matrix(QQ, 2, [1,2,3,4]) 

sage: A \ A 

[1 0] 

[0 1] 

sage: A \ A \ A 

[1 2] 

[3 4] 

sage: A.parent()(1) \ A 

[1 2] 

[3 4] 

sage: A \ (A \ A) 

[ -2 1] 

[ 3/2 -1/2] 

sage: X = A \ (A - 2); X 

[ 5 -2] 

[-3 2] 

sage: A * X 

[-1 2] 

[ 3 2] 

  

Solving over a polynomial ring:: 

  

sage: x = polygen(QQ, 'x') 

sage: A = matrix(2, [x,2*x,-5*x^2+1,3]) 

sage: v = vector([3,4*x - 2]) 

sage: X = A \ v 

sage: X 

((-8*x^2 + 4*x + 9)/(10*x^3 + x), (19*x^2 - 2*x - 3)/(10*x^3 + x)) 

sage: A * X == v 

True 

  

Solving some systems over `\ZZ/n\ZZ`:: 

  

sage: A = Matrix(Zmod(6), 3, 2, [1,2,3,4,5,6]) 

sage: B = vector(Zmod(6), [1,1,1]) 

sage: A.solve_right(B) 

(5, 1) 

sage: B = vector(Zmod(6), [5,1,1]) 

sage: A.solve_right(B) 

Traceback (most recent call last): 

... 

ValueError: matrix equation has no solutions 

sage: A = Matrix(Zmod(128), 2, 3, [23,11,22,4,1,0]) 

sage: B = Matrix(Zmod(128), 2, 1, [1,0]) 

sage: A.solve_right(B) 

[ 1] 

[124] 

[ 1] 

sage: B = B.column(0) 

sage: A.solve_right(B) 

(1, 124, 1) 

  

Solving a system over the p-adics:: 

  

sage: k = Qp(5,4) 

sage: a = matrix(k, 3, [1,7,3,2,5,4,1,1,2]); a 

[ 1 + O(5^4) 2 + 5 + O(5^4) 3 + O(5^4)] 

[ 2 + O(5^4) 5 + O(5^5) 4 + O(5^4)] 

[ 1 + O(5^4) 1 + O(5^4) 2 + O(5^4)] 

sage: v = vector(k, 3, [1,2,3]) 

sage: x = a \ v; x 

(4 + 5 + 5^2 + 3*5^3 + O(5^4), 2 + 5 + 3*5^2 + 5^3 + O(5^4), 1 + 5 + O(5^4)) 

sage: a * x == v 

True 

  

Solving a system of linear equation symbolically using symbolic matrices:: 

  

sage: var('a,b,c,d,x,y') 

(a, b, c, d, x, y) 

sage: A=matrix(SR,2,[a,b,c,d]); A 

[a b] 

[c d] 

sage: result=vector(SR,[3,5]); result 

(3, 5) 

sage: soln=A.solve_right(result) 

sage: soln 

(-b*(3*c/a - 5)/(a*(b*c/a - d)) + 3/a, (3*c/a - 5)/(b*c/a - d)) 

sage: (a*x+b*y).subs(x=soln[0],y=soln[1]).simplify_full() 

3 

sage: (c*x+d*y).subs(x=soln[0],y=soln[1]).simplify_full() 

5 

sage: (A*soln).apply_map(lambda x: x.simplify_full()) 

(3, 5) 

""" 

  

if is_Vector(B): 

if self.nrows() != B.degree(): 

raise ValueError("number of rows of self must equal degree of B") 

else: 

if self.nrows() != B.nrows(): 

raise ValueError("number of rows of self must equal number of rows of B") 

  

K = self.base_ring() 

if not K.is_integral_domain(): 

from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing 

if is_IntegerModRing(K): 

from sage.libs.pari import pari 

A = pari(self.lift()) 

b = pari(B).lift() 

if b.type() == "t_MAT": 

b = b[0] 

elif b.type() == "t_VEC": 

b = b.Col() 

ret = A.matsolvemod(K.cardinality(), b) 

if ret.type() == 't_INT': 

raise ValueError("matrix equation has no solutions") 

ret = ret.Vec().sage() 

if is_Vector(B): 

return (K ** self.ncols())(ret) 

return self.matrix_space(self.ncols(), 1)(ret) 

raise TypeError("base ring must be an integral domain or a ring of integers mod n") 

if not K.is_field(): 

K = K.fraction_field() 

self = self.change_ring(K) 

  

matrix = True 

if is_Vector(B): 

matrix = False 

C = self.matrix_space(self.nrows(), 1)(B.list()) 

else: 

C = B 

  

if not self.is_square(): 

X = self._solve_right_general(C, check=check) 

if not matrix: 

# Convert back to a vector 

return (X.base_ring() ** X.nrows())(X.list()) 

else: 

return X 

  

if self.rank() != self.nrows(): 

X = self._solve_right_general(C, check=check) 

else: 

X = self._solve_right_nonsingular_square(C, check_rank=False) 

  

if not matrix: 

# Convert back to a vector 

return X.column(0) 

else: 

return X 

  

def _solve_right_nonsingular_square(self, B, check_rank=True): 

r""" 

If ``self`` is a matrix `A` of full rank, then this function 

returns a matrix `X` such that `A X = B`. 

  

.. SEEALSO:: 

  

:meth:`solve_right` and :meth:`solve_left` 

  

INPUT: 

  

- ``B`` -- a matrix 

  

- ``check_rank`` -- boolean (default: ``True``) 

  

OUTPUT: matrix 

  

EXAMPLES:: 

  

sage: A = matrix(QQ,3,[1,2,4,5,3,1,1,2,-1]) 

sage: B = matrix(QQ,3,2,[1,5,1,2,1,5]) 

sage: A._solve_right_nonsingular_square(B) 

[ -1/7 -11/7] 

[ 4/7 23/7] 

[ 0 0] 

sage: A._solve_right_nonsingular_square(B, check_rank=False) 

[ -1/7 -11/7] 

[ 4/7 23/7] 

[ 0 0] 

sage: X = A._solve_right_nonsingular_square(B, check_rank=False) 

sage: A*X == B 

True 

""" 

D = self.augment(B) 

D.echelonize() 

return D.matrix_from_columns(range(self.ncols(),D.ncols())) 

  

def pivot_rows(self): 

""" 

Return the pivot row positions for this matrix, which are a topmost 

subset of the rows that span the row space and are linearly 

independent. 

  

OUTPUT: a tuple of integers 

  

EXAMPLES:: 

  

sage: A = matrix(QQ,3,3, [0,0,0,1,2,3,2,4,6]); A 

[0 0 0] 

[1 2 3] 

[2 4 6] 

sage: A.pivot_rows() 

(1,) 

sage: A.pivot_rows() # testing cached value 

(1,) 

""" 

v = self.fetch('pivot_rows') 

if v is not None: 

return tuple(v) 

v = self.transpose().pivots() 

self.cache('pivot_rows', v) 

return v 

  

def _solve_right_general(self, B, check=True): 

r""" 

This is used internally by the ``solve_right`` command 

to solve for self\*X = B when self is not square or not of full 

rank. It does some linear algebra, then solves a full-rank square 

system. 

  

INPUT: 

  

  

- ``B`` - a matrix 

  

- ``check`` - bool (default: True); if False, if there 

is no solution this function will not detect that fact. 

  

  

OUTPUT: matrix 

  

EXAMPLES:: 

  

sage: A = matrix(QQ,2,3, [1,2,3,2,4,6]); B = matrix(QQ,2,2, [6, -6, 12, -12]) 

sage: A._solve_right_general(B) 

[ 6 -6] 

[ 0 0] 

[ 0 0] 

""" 

pivot_cols = self.pivots() 

A = self.matrix_from_columns(pivot_cols) 

pivot_rows = A.pivot_rows() 

A = A.matrix_from_rows(pivot_rows) 

X = A.solve_right(B.matrix_from_rows(pivot_rows), check=False) 

if len(pivot_cols) < self.ncols(): 

# Now we have to put in zeros for the non-pivot ROWS, i.e., 

# make a matrix from X with the ROWS of X interspersed with 

# 0 ROWS. 

Y = X.new_matrix(self.ncols(), X.ncols()) 

# Put the columns of X into the matrix Y at the pivot_cols positions 

for i, c in enumerate(pivot_cols): 

Y.set_row(c, X.row(i)) 

X = Y 

if check: 

# Have to check that we actually solved the equation. 

if self*X != B: 

raise ValueError("matrix equation has no solutions") 

return X 

  

def prod_of_row_sums(self, cols): 

r""" 

Calculate the product of all row sums of a submatrix of `A` 

for a list of selected columns ``cols``. 

  

EXAMPLES:: 

  

sage: a = matrix(QQ, 2,2, [1,2,3,2]); a 

[1 2] 

[3 2] 

sage: a.prod_of_row_sums([0,1]) 

15 

  

Another example:: 

  

sage: a = matrix(QQ, 2,3, [1,2,3,2,5,6]); a 

[1 2 3] 

[2 5 6] 

sage: a.prod_of_row_sums([1,2]) 

55 

  

AUTHORS: 

  

- Jaap Spies (2006-02-18) 

""" 

cdef Py_ssize_t c, row 

pr = 1 

for row from 0 <= row < self._nrows: 

tmp = [] 

for c in cols: 

# if c<0 or c >= self._ncols: 

# raise IndexError("matrix column index out of range") 

tmp.append(self.get_unsafe(row, c)) 

pr = pr * sum(tmp) 

return pr 

  

def elementwise_product(self, right): 

r""" 

Returns the elementwise product of two matrices 

of the same size (also known as the Hadamard product). 

  

INPUT: 

  

- ``right`` - the right operand of the product. A matrix 

of the same size as ``self`` such that multiplication 

of elements of the base rings of ``self`` and ``right`` 

is defined, once Sage's coercion model is applied. If 

the matrices have different sizes, or if multiplication 

of individual entries cannot be achieved, a ``TypeError`` 

will result. 

  

OUTPUT: 

  

A matrix of the same size as ``self`` and ``right``. The 

entry in location `(i,j)` of the output is the product of 

the two entries in location `(i,j)` of ``self`` and 

``right`` (in that order). 

  

The parent of the result is determined by Sage's coercion 

model. If the base rings are identical, then the result 

is dense or sparse according to this property for 

the left operand. If the base rings must be adjusted 

for one, or both, matrices then the result will be sparse 

only if both operands are sparse. No subdivisions are 

present in the result. 

  

If the type of the result is not to your liking, or 

the ring could be "tighter," adjust the operands with 

:meth:`~sage.matrix.matrix0.Matrix.change_ring`. 

Adjust sparse versus dense inputs with the methods 

:meth:`~sage.matrix.matrix1.Matrix.sparse_matrix` and 

:meth:`~sage.matrix.matrix1.Matrix.dense_matrix`. 

  

EXAMPLES:: 

  

sage: A = matrix(ZZ, 2, 3, range(6)) 

sage: B = matrix(QQ, 2, 3, [5, 1/3, 2/7, 11/2, -3/2, 8]) 

sage: C = A.elementwise_product(B) 

sage: C 

[ 0 1/3 4/7] 

[33/2 -6 40] 

sage: C.parent() 

Full MatrixSpace of 2 by 3 dense matrices over Rational Field 

  

  

Notice the base ring of the results in the next two examples. :: 

  

sage: D = matrix(ZZ['x'],2,[1+x^2,2,3,4-x]) 

sage: E = matrix(QQ,2,[1,2,3,4]) 

sage: F = D.elementwise_product(E) 

sage: F 

[ x^2 + 1 4] 

[ 9 -4*x + 16] 

sage: F.parent() 

Full MatrixSpace of 2 by 2 dense matrices over Univariate Polynomial Ring in x over Rational Field 

  

:: 

  

sage: G = matrix(GF(3),2,[0,1,2,2]) 

sage: H = matrix(ZZ,2,[1,2,3,4]) 

sage: J = G.elementwise_product(H) 

sage: J 

[0 2] 

[0 2] 

sage: J.parent() 

Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 3 

  

Non-commutative rings behave as expected. These are the usual quaternions. :: 

  

sage: R.<i,j,k> = QuaternionAlgebra(-1, -1) 

sage: A = matrix(R, 2, [1,i,j,k]) 

sage: B = matrix(R, 2, [i,i,i,i]) 

sage: A.elementwise_product(B) 

[ i -1] 

[-k j] 

sage: B.elementwise_product(A) 

[ i -1] 

[ k -j] 

  

Input that is not a matrix will raise an error. :: 

  

sage: A = random_matrix(ZZ,5,10,x=20) 

sage: A.elementwise_product(vector(ZZ, [1,2,3,4])) 

Traceback (most recent call last): 

... 

TypeError: operand must be a matrix, not an element of Ambient free module of rank 4 over the principal ideal domain Integer Ring 

  

Matrices of different sizes for operands will raise an error. :: 

  

sage: A = random_matrix(ZZ,5,10,x=20) 

sage: B = random_matrix(ZZ,10,5,x=40) 

sage: A.elementwise_product(B) 

Traceback (most recent call last): 

... 

TypeError: incompatible sizes for matrices from: Full MatrixSpace of 5 by 10 dense matrices over Integer Ring and Full MatrixSpace of 10 by 5 dense matrices over Integer Ring 

  

Some pairs of rings do not have a common parent where 

multiplication makes sense. This will raise an error. :: 

  

sage: A = matrix(QQ, 3, 2, range(6)) 

sage: B = matrix(GF(3), 3, [2]*6) 

sage: A.elementwise_product(B) 

Traceback (most recent call last): 

... 

TypeError: no common canonical parent for objects with parents: 'Full MatrixSpace of 3 by 2 dense matrices over Rational Field' and 'Full MatrixSpace of 3 by 2 dense matrices over Finite Field of size 3' 

  

We illustrate various combinations of sparse and dense matrices. 

Notice how if base rings are unequal, both operands must be sparse 

to get a sparse result. :: 

  

sage: A = matrix(ZZ, 5, 6, range(30), sparse=False) 

sage: B = matrix(ZZ, 5, 6, range(30), sparse=True) 

sage: C = matrix(QQ, 5, 6, range(30), sparse=True) 

sage: A.elementwise_product(C).is_dense() 

True 

sage: B.elementwise_product(C).is_sparse() 

True 

sage: A.elementwise_product(B).is_dense() 

True 

sage: B.elementwise_product(A).is_dense() 

True 

  

TESTS: 

  

Implementation for dense and sparse matrices are 

different, this will provide a trivial test that 

they are working identically. :: 

  

sage: A = random_matrix(ZZ, 10, x=1000, sparse=False) 

sage: B = random_matrix(ZZ, 10, x=1000, sparse=False) 

sage: C = A.sparse_matrix() 

sage: D = B.sparse_matrix() 

sage: E = A.elementwise_product(B) 

sage: F = C.elementwise_product(D) 

sage: E.is_dense() and F.is_sparse() and (E == F) 

True 

  

If the ring has zero divisors, the routines for setting 

entries of a sparse matrix should intercept zero results 

and not create an entry. :: 

  

sage: R = Integers(6) 

sage: A = matrix(R, 2, [3, 2, 0, 0], sparse=True) 

sage: B = matrix(R, 2, [2, 3, 1, 0], sparse=True) 

sage: C = A.elementwise_product(B) 

sage: len(C.nonzero_positions()) == 0 

True 

  

AUTHOR: 

  

- Rob Beezer (2009-07-13) 

""" 

# Optimized routines for specialized classes would likely be faster 

# See the "pairwise_product" of vectors for some guidance on doing this 

from sage.structure.element import canonical_coercion 

if not isinstance(right, Matrix): 

raise TypeError('operand must be a matrix, not an element of %s' % right.parent()) 

if (self.nrows() != right.nrows()) or (self.ncols() != right.ncols()): 

raise TypeError('incompatible sizes for matrices from: %s and %s'%(self.parent(), right.parent())) 

if self._parent is not (<Matrix>right)._parent: 

self, right = canonical_coercion(self, right) 

return self._elementwise_product(right) 

  

def permanent(self, algorithm="Ryser"): 

r""" 

Return the permanent of this matrix. 

  

Let `A = (a_{i,j})` be an `m \times n` matrix over any 

commutative ring with `m \le n`. The permanent of `A` is 

  

.. MATH:: 

  

\mathrm{per}(A) 

= \sum_\pi a_{1,\pi(1)} a_{2,\pi(2)} \cdots a_{m,\pi(m)} 

  

where the summation extends over all one-to-one functions 

`\pi` from `\{1, \ldots, m\}` to `\{1, \ldots, n\}`. 

  

The product 

`a_{1,\pi(1)} a_{2,\pi(2)} \cdots a_{m,\pi(m)}` is 

called *diagonal product*. So the permanent of an 

`m \times n` matrix `A` is the sum of all the 

diagonal products of `A`. 

  

By default, this method uses Ryser's algorithm, but setting 

``algorithm`` to "ButeraPernici" you can use the algorithm of Butera and 

Pernici (which is well suited for band matrices, i.e. matrices whose 

entries are concentrated near the diagonal). 

  

INPUT: 

  

- ``A`` -- matrix of size `m \times n` with `m \leq n` 

  

- ``algorithm`` -- either "Ryser" (default) or "ButeraPernici". The 

Butera-Pernici algorithm takes advantage of presence of zeros and is 

very well suited for sparse matrices. 

  

ALGORITHM: 

  

The Ryser algorithm is implemented in the method 

:meth:`_permanent_ryser`. It is a modification of theorem 7.1.1. from 

Brualdi and Ryser: Combinatorial Matrix Theory. Instead of deleting 

columns from `A`, we choose columns from `A` and calculate the product 

of the row sums of the selected submatrix. 

  

The Butera-Pernici algorithm is implemented in the function 

:func:`~sage.matrix.matrix_misc.permanental_minor_polynomial`. It takes 

advantage of cancellations that may occur in the computations. 

  

EXAMPLES:: 

  

sage: A = ones_matrix(4,4) 

sage: A.permanent() 

24 

  

sage: A = matrix(3,6,[1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1]) 

sage: A.permanent() 

36 

sage: B = A.change_ring(RR) 

sage: B.permanent() 

36.0000000000000 

  

The permanent above is directed to the Sloane's sequence :oeis:`A079908` 

("The Dancing School Problems") for which the third term is 36: 

  

:: 

  

sage: oeis(79908) # optional -- internet 

A079908: Solution to the Dancing School Problem with 3 girls and n+3 boys: f(3,n). 

sage: _(3) # optional -- internet 

36 

  

:: 

  

sage: A = matrix(4,5,[1,1,0,1,1,0,1,1,1,1,1,0,1,0,1,1,1,0,1,0]) 

sage: A.permanent() 

32 

  

A huge permanent that can not be reasonably computed with the Ryser 

algorithm (a `50 \times 50` band matrix with width `5`):: 

  

sage: n, w = 50, 5 

sage: A = matrix(ZZ, n, n, lambda i,j: (i+j)%5 + 1 if abs(i-j) <= w else 0) 

sage: A.permanent(algorithm="ButeraPernici") 

57766972735511097036962481710892268404670105604676932908 

  

See Minc: Permanents, Example 2.1, p. 5. 

  

:: 

  

sage: A = matrix(QQ,2,2,[1/5,2/7,3/2,4/5]) 

sage: A.permanent() 

103/175 

  

:: 

  

sage: R.<a> = PolynomialRing(ZZ) 

sage: A = matrix(R,2,2,[a,1,a,a+1]) 

sage: A.permanent() 

a^2 + 2*a 

  

:: 

  

sage: R.<x,y> = PolynomialRing(ZZ,2) 

sage: A = matrix(R,2,2,[x, y, x^2, y^2]) 

sage: A.permanent() 

x^2*y + x*y^2 

  

AUTHORS: 

  

- Jaap Spies (2006-02-16 and 2006-02-21) 

""" 

if algorithm == "Ryser": 

return self._permanent_ryser() 

  

elif algorithm == "ButeraPernici": 

return permanental_minor_polynomial(self, True) 

  

else: 

raise ValueError("algorithm must be one of \"Ryser\" or \"ButeraPernici\".") 

  

def _permanent_ryser(self): 

r""" 

Return the permanent computed using Ryser algorithm. 

  

See :meth:`permanent` for the documentation. 

  

EXAMPLES:: 

  

sage: m = matrix([[1,1],[1,1]]) 

sage: m._permanent_ryser() 

2 

""" 

cdef Py_ssize_t m, n, r 

cdef int sn 

  

perm = 0 

m = self._nrows 

n = self._ncols 

if not m <= n: 

raise ValueError("must have m <= n, but m (=%s) and n (=%s)"%(m,n)) 

  

for r from 1 <= r < m+1: 

lst = _choose(n, r) 

tmp = [] 

for cols in lst: 

tmp.append(self.prod_of_row_sums(cols)) 

s = sum(tmp) 

# sn = (-1)^(m-r) 

if (m - r) % 2 == 0: 

sn = 1 

else: 

sn = -1 

perm = perm + sn * _binomial(n-r, m-r) * s 

return perm 

  

def permanental_minor(self, Py_ssize_t k, algorithm="Ryser"): 

r""" 

Return the permanental `k`-minor of this matrix. 

  

The *permanental* `k`-*minor* of a matrix `A` is the sum of the 

permanents of all possible `k` by `k` submatrices of `A`. Note that the 

maximal permanental minor is just the permanent. 

  

For a (0,1)-matrix `A` the permanental `k`-minor 

counts the number of different selections of `k` 1's of 

`A` with no two of the 1's on the same row and no two of the 

1's on the same column. 

  

See Brualdi and Ryser: Combinatorial Matrix Theory, p. 203. Note 

the typo `p_0(A) = 0` in that reference! For applications 

see Theorem 7.2.1 and Theorem 7.2.4. 

  

.. SEEALSO:: 

  

The method :meth:`rook_vector` returns the list of all permanental 

minors. 

  

INPUT: 

  

- ``k`` -- the size of the minor 

  

- ``algorithm`` -- either "Ryser" (default) or "ButeraPernici". The 

Butera-Pernici algorithm is well suited for band matrices. 

  

EXAMPLES:: 

  

sage: A = matrix(4,[1,0,1,0,1,0,1,0,1,0,10,10,1,0,1,1]) 

sage: A.permanental_minor(2) 

114 

  

:: 

  

sage: A = matrix(3,6,[1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1]) 

sage: A.permanental_minor(0) 

1 

sage: A.permanental_minor(1) 

12 

sage: A.permanental_minor(2) 

40 

sage: A.permanental_minor(3) 

36 

  

Note that if `k = m = n`, the permanental `k`-minor equals 

`\mathrm{per}(A)`:: 

  

sage: A.permanent() 

36 

  

The permanental minors of the "complement" matrix of `A` is 

related to the permanent of `A`:: 

  

sage: m, n = 3, 6 

sage: C = matrix(m, n, lambda i,j: 1 - A[i,j]) 

sage: sum((-1)^k * C.permanental_minor(k)*factorial(n-k)/factorial(n-m) for k in range(m+1)) 

36 

  

See Theorem 7.2.1 of Brualdi and Ryser: Combinatorial Matrix 

Theory: per(A) 

  

TESTS:: 

  

sage: A.permanental_minor(5) 

0 

  

AUTHORS: 

  

- Jaap Spies (2006-02-19) 

""" 

if algorithm == "Ryser": 

return self._permanental_minor_ryser(k) 

  

elif algorithm == "ButeraPernici": 

p = permanental_minor_polynomial(self, prec=k+1) 

return p[k] 

  

else: 

raise ValueError("algorithm must be one of \"Ryser\" or \"ButeraPernici\".") 

  

def _permanental_minor_ryser(self, Py_ssize_t k): 

r""" 

Compute the `k`-th permanental minor using Ryser algorithm. 

  

See :meth:`permanental_minor` for the documentation. 

  

EXAMPLES:: 

  

sage: m = matrix([[1,2,1],[3,4,3],[5,6,5]]) 

sage: m._permanental_minor_ryser(1) 

30 

sage: m._permanental_minor_ryser(2) 

174 

sage: m._permanental_minor_ryser(3) 

136 

""" 

m = self._nrows 

n = self._ncols 

  

R = self._base_ring 

if k == 0: 

return R.one() 

if k > m: 

return R.zero() 

  

pm = 0 

for cols in _choose(n,k): 

for rows in _choose(m,k): 

pm = pm + self.matrix_from_rows_and_columns(rows, cols).permanent() 

return pm 

  

def pseudoinverse(self, *, algorithm=None): 

""" 

Return the Moore-Penrose pseudoinverse of this matrix. 

  

INPUT: 

  

- ``algorithm`` (default: guess) -- one of the following: 

  

- ``"numpy"`` -- Use numpy's ``linalg.pinv()`` which is 

suitable over real or complex fields. 

  

- ``"exact"`` -- Use a simple algorithm which is not 

numerically stable but useful over exact fields. Assume that 

no conjugation is needed, that the conjugate transpose is 

just the transpose. 

  

- ``"exactconj"`` -- Like ``exact`` but use the conjugate 

transpose. 

  

OUTPUT: a matrix 

  

EXAMPLES:: 

  

sage: M = diagonal_matrix(CDF, [0, I, 1+I]) 

sage: M 

[ 0.0 0.0 0.0] 

[ 0.0 1.0*I 0.0] 

[ 0.0 0.0 1.0 + 1.0*I] 

sage: M.pseudoinverse() # tol 1e-15 

[ 0.0 0.0 0.0] 

[ 0.0 -1.0*I 0.0] 

[ 0.0 0.0 0.5 - 0.5*I] 

  

We check the properties of the pseudoinverse over an exact 

field:: 

  

sage: M = random_matrix(QQ, 6, 3) * random_matrix(QQ, 3, 5) 

sage: Mx = M.pseudoinverse() 

sage: M * Mx * M == M 

True 

sage: Mx * M * Mx == Mx 

True 

sage: (M * Mx).is_symmetric() 

True 

sage: (Mx * M).is_symmetric() 

True 

  

Beware that the ``exact`` algorithm is not numerically stable, 

but the default ``numpy`` algorithm is:: 

  

sage: M = matrix(RR, 3, 3, [1,2,3,1/3,2/3,3/3,1/5,2/5,3/5]) 

sage: M.pseudoinverse() # tol 1e-15 

[0.0620518477661335 0.0206839492553778 0.0124103695532267] 

[ 0.124103695532267 0.0413678985107557 0.0248207391064534] 

[ 0.186155543298400 0.0620518477661335 0.0372311086596801] 

sage: M.pseudoinverse(algorithm="numpy") # tol 1e-15 

[0.0620518477661335 0.0206839492553778 0.0124103695532267] 

[ 0.124103695532267 0.0413678985107557 0.0248207391064534] 

[ 0.186155543298400 0.0620518477661335 0.0372311086596801] 

sage: M.pseudoinverse(algorithm="exact") 

[ 0.125000000000000 0.0625000000000000 0.0312500000000000] 

[ 0.250000000000000 0.125000000000000 0.0625000000000000] 

[ 0.000000000000000 0.000000000000000 0.0625000000000000] 

  

When multiplying the given matrix with the pseudoinverse, the 

result is symmetric for the ``exact`` algorithm or hermitian 

for the ``exactconj`` algorithm:: 

  

sage: M = matrix(QQbar, 2, 2, [1, sqrt(-3), -sqrt(-3), 3]) 

sage: M * M.pseudoinverse() 

[ 0.2500000000000000? 0.4330127018922193?*I] 

[-0.4330127018922193?*I 0.750000000000000?] 

sage: M * M.pseudoinverse(algorithm="exactconj") 

[ 1/4 0.4330127018922193?*I] 

[-0.4330127018922193?*I 3/4] 

sage: M * M.pseudoinverse(algorithm="exact") 

[ -1/2 0.866025403784439?*I] 

[0.866025403784439?*I 3/2] 

  

For an invertible matrix, the pseudoinverse is just the 

inverse:: 

  

sage: M = matrix([[1,2], [3,4]]) 

sage: ~M 

[ -2 1] 

[ 3/2 -1/2] 

sage: M.pseudoinverse() 

[ -2 1] 

[ 3/2 -1/2] 

  

Numpy gives a strange answer due to rounding errors:: 

  

sage: M.pseudoinverse(algorithm="numpy") # random 

[-1286742750677287/643371375338643 1000799917193445/1000799917193444] 

[ 519646110850445/346430740566963 -300239975158034/600479950316067] 

  

TESTS:: 

  

sage: M.pseudoinverse(algorithm="exact") 

[ -2 1] 

[ 3/2 -1/2] 

sage: M.pseudoinverse(algorithm="whatever") 

Traceback (most recent call last): 

... 

ValueError: unknown algorithm 'whatever', valid values are ('numpy', 'exact', 'exactconj') 

sage: M.change_ring(RealField(54)).pseudoinverse() 

Traceback (most recent call last): 

... 

NotImplementedError: pseudoinverse for real/complex field is only implemented for <= 53 bits of precision 

""" 

ring = self.base_ring() 

if algorithm is None: 

# Choose algorithm depending on base ring 

is_complex = ComplexField(2).has_coerce_map_from(ring) 

if is_complex: 

if ring.is_exact(): 

is_real = RealField(2).has_coerce_map_from(ring) 

algorithm = "exact" if is_real else "exactconj" 

else: 

if ring.precision() <= 53: 

algorithm = "numpy" 

else: 

raise NotImplementedError("pseudoinverse for real/complex field is only implemented for <= 53 bits of precision") 

else: 

algorithm = "exact" 

else: 

algos = ("numpy", "exact", "exactconj") 

if algorithm not in algos: 

raise ValueError("unknown algorithm {!r}, valid values are {}".format(algorithm, algos)) 

  

if algorithm == "numpy": 

from numpy.linalg import pinv 

from sage.matrix.constructor import matrix 

ans = pinv(self.numpy()) 

return matrix(ring.fraction_field(), ans) 

  

# We use a simple algorithm taken from 

# https://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_pseudoinverse#Rank_decomposition 

# Write self as A * B such that A and B both have full rank. 

B = self.row_space().basis_matrix() 

A = B.solve_left(self) 

  

if algorithm.endswith("conj"): 

At = A.conjugate_transpose() 

Bt = B.conjugate_transpose() 

else: 

At = A.transpose() 

Bt = B.transpose() 

  

# Now the pseudoinverse is B^t (A^t A B B^t)^-1 A^t. 

Q = (At * A) * (B * Bt) 

return Bt * ~Q * At 

  

def rook_vector(self, algorithm="ButeraPernici", complement=False, use_complement=None): 

r""" 

Return the rook vector of this matrix. 

  

Let `A` be an `m` by `n` (0,1)-matrix. We identify `A` with a chessboard 

where rooks can be placed on the fields `(i, j)` with `A_{i,j} = 1`. The 

number `r_k = p_k(A)` (the permanental `k`-minor) counts the number of 

ways to place `k` rooks on this board so that no rook can attack 

another. 

  

The *rook vector* of the matrix `A` is the list consisting of `r_0, 

r_1, \ldots, r_h`, where `h = min(m,n)`. The *rook polynomial* is defined by 

`r(x) = \sum_{k=0}^h r_k x^k`. 

  

The rook vector can be generalized to matrices defined over any rings 

using permanental minors. Among the available algorithms, only "Godsil" 

needs the condition on the entries to be either `0` or `1`. 

  

See :wikipedia:`Rook_polynomial` for more information and also the 

method :meth:`permanental_minor` to compute individual permanental 

minor. 

  

See also ``sage.matrix.matrix2.permanental_minor_polynomial`` 

and the graph method ``matching_polynomial``. 

  

INPUT: 

  

- ``self`` -- an `m` by `n` matrix 

  

- ``algorithm`` -- a string which must be either "Ryser" or 

"ButeraPernici" (default) or "Godsil"; Ryser one might be faster on 

simple and small instances. Godsil only accepts input in 0,1. 

  

- ``complement`` -- boolean (default: ``False``) whether we consider the 

rook vector of the complement matrix. If set to ``True`` then the 

matrix must have entries in {0, 1} and the complement matrix is the 

one for which the 0's are replaced by 1's and 1's by 0's. 

  

- ``use_complement`` -- Boolean (default: ``None``) whether to compute the 

rook vector of a (0,1)-matrix from its complement. By default this is 

determined by the density of ones in the matrix. 

  

EXAMPLES: 

  

The standard chessboard is an `8` by `8` grid in which any positions is 

allowed. In that case one gets that the number of ways to position `4` 

non-attacking rooks is `117600` while for `8` rooks it is `40320`:: 

  

sage: ones_matrix(8,8).rook_vector() 

[1, 64, 1568, 18816, 117600, 376320, 564480, 322560, 40320] 

  

These numbers are the coefficients of a modified Laguerre polynomial:: 

  

sage: x = polygen(QQ) 

sage: factorial(8) * laguerre(8,-x) 

x^8 + 64*x^7 + 1568*x^6 + 18816*x^5 + 117600*x^4 + 376320*x^3 + 

564480*x^2 + 322560*x + 40320 

  

The number of derangements of length `n` is the permanent 

of a matrix with 0 on the diagonal and 1 elsewhere; 

for `n=21` it is `18795307255050944540` (see :oeis:`A000166`): 

  

sage: A = identity_matrix(21) 

sage: A.rook_vector(complement=True)[-1] 

18795307255050944540 

sage: Derangements(21).cardinality() 

18795307255050944540 

  

An other example that we convert into a rook polynomial:: 

  

sage: A = matrix(3,6, [1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1]) 

sage: A 

[1 1 1 1 0 0] 

[0 1 1 1 1 0] 

[0 0 1 1 1 1] 

sage: A.rook_vector() 

[1, 12, 40, 36] 

  

sage: R = PolynomialRing(ZZ, 'x') 

sage: R(A.rook_vector()) 

36*x^3 + 40*x^2 + 12*x + 1 

  

Different algorithms are available:: 

  

sage: A = matrix([[1,0,0,1],[0,1,1,0],[0,1,1,0],[1,0,0,1]]) 

sage: A.rook_vector(algorithm="ButeraPernici") 

[1, 8, 20, 16, 4] 

sage: A.rook_vector(algorithm="Ryser") 

[1, 8, 20, 16, 4] 

sage: A.rook_vector(algorithm="Godsil") 

[1, 8, 20, 16, 4] 

  

When the matrix `A` has more ones then zeroes it is usually faster 

to compute the rook polynomial of the complementary matrix, with 

zeroes and ones interchanged, and use the inclusion-exclusion theorem, 

giving for a `m \times n` matrix `A` with complementary matrix `B` 

  

.. MATH:: 

  

r_k(A) = \sum_{j=0}^k (-1)^j \binom{m-j}{k-j} \binom{n-j}{k-j} (k-j)! r_j(B) 

  

see [Rio1958]_ or the introductory text [AS2011]_. This can be done 

setting the argument ``use_complement`` to ``True``. 

  

An example with an exotic matrix (for which only Butera-Pernici and 

Ryser algorithms are available):: 

  

sage: R.<x,y> = PolynomialRing(GF(5)) 

sage: A = matrix(R,[[1,x,y],[x*y,x**2+y,0]]) 

sage: A.rook_vector(algorithm="ButeraPernici") 

[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y] 

sage: A.rook_vector(algorithm="Ryser") 

[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y] 

sage: A.rook_vector(algorithm="Godsil") 

Traceback (most recent call last): 

... 

ValueError: coefficients must be zero or one, but we have 'x' in position (0,1). 

sage: B = A.transpose() 

sage: B.rook_vector(algorithm="ButeraPernici") 

[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y] 

sage: B.rook_vector(algorithm="Ryser") 

[1, x^2 + x*y + x + 2*y + 1, 2*x^2*y + x*y^2 + x^2 + y^2 + y] 

  

TESTS:: 

  

sage: matrix([[0,0],[0,0]]).rook_vector(algorithm="ButeraPernici") 

[1, 0, 0] 

sage: matrix([[0,0],[0,0]]).rook_vector(algorithm="Ryser") 

[1, 0, 0] 

sage: matrix([[0,0],[0,0]]).rook_vector(algorithm="Godsil") 

[1, 0, 0] 

sage: matrix.ones(4, 2).rook_vector("Ryser") 

[1, 8, 12] 

sage: matrix.ones(4, 2).rook_vector("Godsil") 

[1, 8, 12] 

sage: m = matrix(ZZ,4,5) 

sage: m[:4,:4] = identity_matrix(4) 

sage: for algorithm in ("Godsil","Ryser","ButeraPernici"): 

....: v = m.rook_vector(complement=True, use_complement=True, algorithm=algorithm) 

....: if v != [1, 16, 78, 128, 53]: 

....: print("ERROR with algorithm={} use_complement=True".format(algorithm)) 

....: v = m.rook_vector(complement=True, use_complement=False, algorithm=algorithm) 

....: v = m.rook_vector(complement=True, use_complement=False) 

....: if v != [1, 16, 78, 128, 53]: 

....: print("ERROR with algorithm={} use_complement=False".format(algorithm)) 

  

AUTHORS: 

  

- Jaap Spies (2006-02-24) 

- Mario Pernici (2014-07-01) 

""" 

cdef Py_ssize_t i,j 

cdef unsigned int num_ones 

cdef int m = self._nrows 

cdef int n = self._ncols 

cdef int mn = min(m, n) 

cdef Matrix B 

zero = self.base_ring().zero() 

one = self.base_ring().one() 

  

# we first run through the coefficients of the matrix to compute the 

# number of non-zero coefficients and to see whether or not it contains 

# only elements in {0,1}... but this is not always needed 

if complement or use_complement is None or algorithm == "Godsil": 

# z2 flag is True if all coefficients belong to {0,1} 

z2 = True 

num_ones = 1 

for i in range(m): 

for j in range(n): 

x = self.get_unsafe(i,j) 

if x != zero: 

if x != one: 

z2 = False 

break 

else: 

num_ones += 1 

else: 

continue 

break 

  

if not z2 and (complement or algorithm == "Godsil"): 

raise ValueError("coefficients must be zero or one, but we have '{}' in position ({},{}).".format(x,i,j)) 

  

if use_complement is None: 

use_complement = z2 and num_ones > 0.55 * m * n 

  

if use_complement: 

B = self.new_matrix() 

for i in range(m): 

for j in range(n): 

B.set_unsafe(i, j, one-self.get_unsafe(i, j)) 

b = B.rook_vector(algorithm=algorithm, use_complement=False) 

complement = not complement 

  

elif algorithm == "Ryser": 

b = [self.permanental_minor(k,algorithm="Ryser") 

for k in range(mn + 1)] 

  

elif algorithm == "ButeraPernici": 

p = permanental_minor_polynomial(self) 

b = [p[k] for k in range(mn + 1)] 

  

elif algorithm == "Godsil": 

from sage.graphs.bipartite_graph import BipartiteGraph 

p = BipartiteGraph(self).matching_polynomial() 

d = p.degree() 

b = [p[i] * (-1)**((d - i)//2) for i in range(d, d-2*mn-1, -2)] 

  

else: 

raise ValueError('algorithm must be one of "Ryser", "ButeraPernici" or "Godsil".') 

  

# now compute the permanental minor of the complement matrix if needed 

if complement: 

a = [one] 

c1 = 1 

for k in range(1, mn + 1): 

c1 = (c1 * (m-k+1) * (n-k+1)) // k 

c = c1 

s = c*b[0] + (-one)**k*b[k] 

for j in range(1, k): 

c = -c * (k-j+1) // ((m-j+1) * (n-j+1)) 

s += c * b[j] 

a.append(s) 

return a 

else: 

return b 

  

def minors(self, k): 

r""" 

Return the list of all `k \times k` minors of self. 

  

Let `A` be an `m \times n` matrix and `k` an integer with 

`0 \leq k`, `k \leq m` and `k \leq n`. 

A `k \times k` minor of `A` is the determinant of a 

`k \times k` matrix obtained from `A` by deleting `m - k` 

rows and `n - k` columns. 

There are no `k \times k` minors of `A` if `k` is larger 

than either `m` or `n`. 

  

The returned list is sorted in lexicographical row major ordering, 

e.g., if A is a `3 \times 3` matrix then the minors returned are 

with these rows/columns: [ [0, 1]x[0, 1], [0, 1]x[0, 2], [0, 1]x[1, 2], 

[0, 2]x[0, 1], [0, 2]x[0, 2], [0, 2]x[1, 2], [1, 2]x[0, 1], [1, 

2]x[0, 2], [1, 2]x[1, 2] ]. 

  

INPUT: 

  

- ``k`` -- integer 

  

EXAMPLES:: 

  

sage: A = Matrix(ZZ,2,3,[1,2,3,4,5,6]); A 

[1 2 3] 

[4 5 6] 

sage: A.minors(2) 

[-3, -6, -3] 

sage: A.minors(1) 

[1, 2, 3, 4, 5, 6] 

sage: A.minors(0) 

[1] 

sage: A.minors(5) 

[] 

  

:: 

  

sage: k = GF(37) 

sage: P.<x0,x1,x2> = PolynomialRing(k) 

sage: A = Matrix(P,2,3,[x0*x1, x0, x1, x2, x2 + 16, x2 + 5*x1 ]) 

sage: A.minors(2) 

[x0*x1*x2 + 16*x0*x1 - x0*x2, 5*x0*x1^2 + x0*x1*x2 - x1*x2, 5*x0*x1 + x0*x2 - x1*x2 - 16*x1] 

  

This test addresses an issue raised at :trac:`20512`:: 

  

sage: A.minors(0)[0].parent() == P 

True 

""" 

from sage.combinat.combination import Combinations 

if k == 0: 

return [self.base_ring().one()] 

all_rows = range(self.nrows()) 

all_cols = range(self.ncols()) 

m = [] 

for rows in Combinations(all_rows,k): 

for cols in Combinations(all_cols,k): 

m.append(self.matrix_from_rows_and_columns(rows,cols).determinant()) 

return m 

  

def determinant(self, algorithm=None): 

r""" 

Returns the determinant of self. 

  

ALGORITHM: 

  

For small matrices (n less than 4), this is computed using the naive 

formula. In the specific case of matrices over the integers modulo a 

non-prime, the determinant of a lift is computed over the integers. 

In general, the characteristic polynomial is computed either using 

the Hessenberg form (specified by ``"hessenberg"``) or the generic 

division-free algorithm (specified by ``"df"``). When the base ring 

is an exact field, the default choice is ``"hessenberg"``, otherwise 

it is ``"df"``. Note that for matrices over most rings, more 

sophisticated algorithms can be used. (Type ``A.determinant?`` to 

see what is done for a specific matrix ``A``.) 

  

INPUT: 

  

- ``algorithm`` - string: 

- ``"df"`` - Generic O(n^4) division-free algorithm 

- ``"hessenberg"`` - Use the Hessenberg form of the matrix 

  

EXAMPLES:: 

  

sage: A = MatrixSpace(Integers(8),3)([1,7,3, 1,1,1, 3,4,5]) 

sage: A.determinant() 

6 

sage: A.determinant() is A.determinant() 

True 

sage: A[0,0] = 10 

sage: A.determinant() 

7 

  

We compute the determinant of the arbitrary 3x3 matrix:: 

  

sage: R = PolynomialRing(QQ,9,'x') 

sage: A = matrix(R,3,R.gens()) 

sage: A 

[x0 x1 x2] 

[x3 x4 x5] 

[x6 x7 x8] 

sage: A.determinant() 

-x2*x4*x6 + x1*x5*x6 + x2*x3*x7 - x0*x5*x7 - x1*x3*x8 + x0*x4*x8 

  

We create a matrix over `\ZZ[x,y]` and compute its 

determinant. 

  

:: 

  

sage: R.<x,y> = PolynomialRing(IntegerRing(),2) 

sage: A = MatrixSpace(R,2)([x, y, x**2, y**2]) 

sage: A.determinant() 

-x^2*y + x*y^2 

  

A matrix over a non-domain:: 

  

sage: m = matrix(Integers(4), 2, [1,2,2,3]) 

sage: m.determinant() 

3 

  

TESTS:: 

  

sage: A = matrix(5, 5, [next_prime(i^2) for i in range(25)]) 

sage: B = MatrixSpace(ZZ['x'], 5, 5)(A) 

sage: A.det() - B.det() 

0 

  

We verify that :trac:`5569` is resolved (otherwise the following 

would hang for hours):: 

  

sage: d = random_matrix(GF(next_prime(10^20)),50).det() 

sage: d = random_matrix(Integers(10^50),50).det() 

  

We verify that :trac:`7704` is resolved:: 

  

sage: matrix(ZZ, {(0,0):1,(1,1):2,(2,2):3,(3,3):4}).det() 

24 

sage: matrix(QQ, {(0,0):1,(1,1):2,(2,2):3,(3,3):4}).det() 

24 

  

We verify that :trac:`10063` is resolved:: 

  

sage: A = GF(2)['x,y,z'] 

sage: A.inject_variables() 

Defining x, y, z 

sage: R = A.quotient(x^2 + 1).quotient(y^2 + 1).quotient(z^2 + 1) 

sage: R.inject_variables() 

Defining xbarbarbar, ybarbarbar, zbarbarbar 

sage: M = matrix([[1,1,1,1],[xbarbarbar,ybarbarbar,1,1],[0,1,zbarbarbar,1],[xbarbarbar,zbarbarbar,1,1]]) 

sage: M.determinant() 

xbarbarbar*ybarbarbar*zbarbarbar + xbarbarbar*ybarbarbar + xbarbarbar*zbarbarbar + ybarbarbar*zbarbarbar + xbarbarbar + ybarbarbar + zbarbarbar + 1 

  

Check that the determinant is computed from a cached charpoly 

properly:: 

  

sage: A = matrix(RR, [ [1, 0, 1/2], 

....: [0, 1, 0 ], 

....: [0, 0, -2 ] ]) 

sage: B = copy(A) 

sage: _ = A.charpoly() 

sage: A.determinant() == B.determinant() 

True 

  

AUTHORS: 

  

- Unknown: No author specified in the file from 2009-06-25 

- Sebastian Pancratz (2009-06-25): Use the division-free 

algorithm for charpoly 

- Thierry Monteil (2010-10-05): Bugfix for :trac:`10063`, 

so that the determinant is computed even for rings for which 

the is_field method is not implemented. 

""" 

  

from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing 

  

if self._nrows != self._ncols: 

raise ValueError("self must be a square matrix") 

  

d = self.fetch('det') 

if not d is None: 

return d 

  

# If charpoly known, then det is easy. 

f = self.fetch('charpoly') 

if f is not None: 

c = f[0] 

if self._nrows % 2 != 0: 

c = -c 

d = self._coerce_element(c) 

self.cache('det', d) 

return d 

  

cdef Py_ssize_t n 

n = self._ncols 

R = self._base_ring 

  

# For small matrices, you can't beat the naive formula. 

if n <= 3: 

if n == 0: 

d = R(1) 

elif n == 1: 

d = self.get_unsafe(0,0) 

elif n == 2: 

d = self.get_unsafe(0,0)*self.get_unsafe(1,1) - self.get_unsafe(1,0)*self.get_unsafe(0,1) 

elif n == 3: 

d = self.get_unsafe(0,0) * (self.get_unsafe(1,1)*self.get_unsafe(2,2) - self.get_unsafe(1,2)*self.get_unsafe(2,1)) \ 

- self.get_unsafe(1,0) * (self.get_unsafe(0,1)*self.get_unsafe(2,2) - self.get_unsafe(0,2)*self.get_unsafe(2,1)) \ 

+ self.get_unsafe(2,0) * (self.get_unsafe(0,1)*self.get_unsafe(1,2) - self.get_unsafe(0,2)*self.get_unsafe(1,1)) 

self.cache('det', d) 

return d 

  

# Special case for Z/nZ or GF(p): 

if is_IntegerModRing(R) and self.is_dense(): 

import sys 

# If the characteristic is prime and smaller than a machine 

# word, use PARI. 

ch = R.characteristic() 

if ch.is_prime() and ch < (2*sys.maxsize): 

d = R(self.__pari__().matdet()) 

else: 

# Lift to ZZ and compute there. 

d = R(self.apply_map(lambda x : x.lift_centered()).det()) 

self.cache('det', d) 

return d 

  

# N.B. The following comment should be obsolete now that the generic 

# code to compute the determinant has been replaced by generic 

# division-free code to compute the characteristic polynomial and read 

# off the determinant from this. 

# 

# If R is an exact integral domain, we could get the det by computing 

# charpoly. The generic fraction field implementation is so slow that 

# the naive algorithm is much faster in practice despite 

# asymptotics. 

# TODO: Find a reasonable cutoff point. (This is field specific, but 

# seems to be quite large for Q[x].) 

if algorithm is None: 

try: 

R_is_field_attempt = R.is_field() 

except NotImplementedError: 

R_is_field_attempt = False 

if (algorithm is None and R_is_field_attempt and R.is_exact()) or (algorithm == "hessenberg"): 

try: 

c = self.charpoly('x', algorithm="hessenberg")[0] 

except ValueError: 

# Hessenberg algorithm not supported, so we use whatever the default algorithm is. 

c = self.charpoly('x')[0] 

if self._nrows % 2: 

c = -c 

d = self._coerce_element(c) 

self.cache('det', d) 

return d 

  

# Generic division-free algorithm to compute the characteristic 

# polynomial. 

# 

# N.B. The case of symbolic rings is quite specific. It would be 

# nice to avoid hardcoding a reserved variable name as below, as this 

# is then assumed to not be a variable in the symbolic ring. But this 

# resulted in further exceptions/ errors. 

from sage.symbolic.ring import is_SymbolicExpressionRing 

  

var = 'A0123456789' if is_SymbolicExpressionRing(R) else 'x' 

try: 

c = self.charpoly(var, algorithm="df")[0] 

except ValueError: 

# Division free algorithm not supported, so we use whatever the default algorithm is. 

c = self.charpoly(var)[0] 

  

if self._nrows % 2: 

c = -c 

d = self._coerce_element(c) 

self.cache('det', d) 

return d 

  

cdef _det_by_minors(self, Py_ssize_t level): 

""" 

Compute the determinant of the upper-left level x level submatrix 

of self. Does not handle degenerate cases, level MUST be >= 2 

""" 

cdef Py_ssize_t n, i 

if level == 2: 

return self.get_unsafe(0,0) * self.get_unsafe(1,1) - self.get_unsafe(0,1) * self.get_unsafe(1,0) 

else: 

level -= 1 

d = self.get_unsafe(level,level) * self._det_by_minors(level) 

# on each iteration, row i will be missing in the first (level) rows 

# swapping is much faster than taking submatrices 

for i from level > i >= 0: 

self.swap_rows(level, i) 

if (level - i) % 2: 

d -= self.get_unsafe(level,level) * self._det_by_minors(level) 

else: 

d += self.get_unsafe(level,level) * self._det_by_minors(level) 

# undo all our permutations to get us back to where we started 

for i from 0 <= i < level: 

self.swap_rows(level, i) 

return d 

  

def pfaffian(self, algorithm=None, check=True): 

r""" 

Return the Pfaffian of ``self``, assuming that ``self`` is an 

alternating matrix. 

  

INPUT: 

  

- ``algorithm`` -- string, the algorithm to use; currently the 

following algorithms have been implemented: 

  

* ``'definition'`` - using the definition given by perfect 

matchings 

  

- ``check`` (default: ``True``) -- Boolean determining whether to 

check ``self`` for alternatingness and squareness. This has to 

be set to ``False`` if ``self`` is defined over a non-discrete 

ring. 

  

The Pfaffian of an alternating matrix is defined as follows: 

  

Let `A` be an alternating `k \times k` matrix over a commutative 

ring. (Here, "alternating" means that `A^T = -A` and that the 

diagonal entries of `A` are zero.) 

If `k` is odd, then the Pfaffian of the matrix `A` is 

defined to be `0`. Let us now define it when `k` is even. In this 

case, set `n = k/2` (this is an integer). For every `i` and `j`, 

we denote the `(i, j)`-th entry of `A` by `a_{i, j}`. Let `M` 

denote the set of all perfect matchings of the set 

`\{ 1, 2, \ldots, 2n \}` (see 

:class:`sage.combinat.perfect_matching.PerfectMatchings` ). 

For every matching `m \in M`, define the sign `\mathrm{sign}(m)` 

of `m` by writing `m` as `\{ \{ i_1, j_1 \}, \{ i_2, j_2 \}, 

\ldots, \{ i_n, j_n \} \}` with `i_k < j_k` for all `k`, and 

setting `\mathrm{sign}(m)` to be the sign of the permutation 

`( i_1, j_1, i_2, j_2, \ldots, i_n, j_n )` (written here in 

one-line notation). For every matching `m \in M`, define the 

weight `w(m)` of `m` by writing `m` as 

`\{ \{ i_1, j_1 \}, \{ i_2, j_2 \}, \ldots, \{ i_n, j_n \} \}` 

with `i_k < j_k` for all `k`, and setting 

`w(m) = a_{i_1, j_1} a_{i_2, j_2} \cdots a_{i_n, j_n}`. Now, the 

Pfaffian of the matrix `A` is defined to be the sum 

  

.. MATH:: 

  

\sum_{m \in M} \mathrm{sign}(m) w(m). 

  

The Pfaffian of `A` is commonly denoted by `\mathrm{Pf}(A)`. It 

is well-known that `(\mathrm{Pf}(A))^2 = \det A` for every 

alternating matrix `A`, and that 

`\mathrm{Pf} (U^T A U) = \det U \cdot \mathrm{Pf}(A)` for any 

`n \times n` matrix `U` and any alternating `n \times n` 

matrix `A`. 

  

See [Knu1995]_, [DW1995]_ and [Rot2001]_, just to name three 

sources, for further properties of Pfaffians. 

  

ALGORITHM: 

  

The current implementation uses the definition given above. 

It checks alternatingness of the matrix ``self`` only if 

``check`` is ``True`` (this is important because even if ``self`` 

is alternating, a non-discrete base ring might prevent Sage 

from being able to check this). 

  

.. TODO:: 

  

Implement faster algorithms, including a division-free one. 

Does [Rot2001]_, section 3.3 give one? 

  

Check the implementation of the matchings used here for 

performance? 

  

EXAMPLES: 

  

A `3 \times 3` alternating matrix has Pfaffian 0 independently 

of its entries:: 

  

sage: MSp = MatrixSpace(Integers(27), 3) 

sage: A = MSp([0, 2, -3, -2, 0, 8, 3, -8, 0]) 

sage: A.pfaffian() 

0 

sage: parent(A.pfaffian()) 

Ring of integers modulo 27 

  

The Pfaffian of a `2 \times 2` alternating matrix is just its 

northeast entry:: 

  

sage: MSp = MatrixSpace(QQ, 2) 

sage: A = MSp([0, 4, -4, 0]) 

sage: A.pfaffian() 

4 

sage: parent(A.pfaffian()) 

Rational Field 

  

The Pfaffian of a `0 \times 0` alternating matrix is `1`:: 

  

sage: MSp = MatrixSpace(ZZ, 0) 

sage: A = MSp([]) 

sage: A.pfaffian() 

1 

sage: parent(A.pfaffian()) 

Integer Ring 

  

Let us compute the Pfaffian of a generic `4 \times 4` 

alternating matrix:: 

  

sage: R = PolynomialRing(QQ, 'x12,x13,x14,x23,x24,x34') 

sage: x12, x13, x14, x23, x24, x34 = R.gens() 

sage: A = matrix(R, [[ 0, x12, x13, x14], 

....: [-x12, 0, x23, x24], 

....: [-x13, -x23, 0, x34], 

....: [-x14, -x24, -x34, 0]]) 

sage: A.pfaffian() 

x14*x23 - x13*x24 + x12*x34 

sage: parent(A.pfaffian()) 

Multivariate Polynomial Ring in x12, x13, x14, x23, x24, x34 over Rational Field 

  

The Pfaffian of an alternating matrix squares to its 

determinant:: 

  

sage: A = [[0] * 6 for i in range(6)] 

sage: for i in range(6): 

....: for j in range(i): 

....: u = floor(random() * 10) 

....: A[i][j] = u 

....: A[j][i] = -u 

....: A[i][i] = 0 

sage: AA = Matrix(ZZ, A) 

sage: AA.pfaffian() ** 2 == AA.det() 

True 

  

AUTHORS: 

  

- Darij Grinberg (1 Oct 2013): first (slow) 

implementation. 

""" 

k = self._nrows 

  

if check: 

if k != self._ncols: 

raise ValueError("self must be a square matrix") 

if not self.is_alternating(): 

raise ValueError("self must be alternating, which includes the diagonal entries being 0") 

  

R = self.base_ring() 

  

if k % 2 == 1: 

return R.zero() 

  

if k == 0: 

return R.one() 

  

n = k // 2 

  

res = R.zero() 

  

from sage.combinat.perfect_matching import PerfectMatchings 

from sage.misc.flatten import flatten 

from sage.misc.misc_c import prod 

from sage.combinat.permutation import Permutation 

for m in PerfectMatchings(k): 

# We only need each edge of the matching to be sorted, 

# not the totality of edges. 

edges = [sorted(edge) for edge in list(m)] 

sgn = Permutation(flatten(edges)).sign() 

# Subtract 1 from everything for indexing purposes: 

edges2 = [[i-1 for i in edge] for edge in edges] 

# Product without base case since k == 0 case has 

# already been dealt with: 

res += sgn * prod([self.get_unsafe(edge[0], edge[1]) for edge in edges2]) 

  

return res 

  

# shortcuts 

def det(self, *args, **kwds): 

""" 

Synonym for self.determinant(...). 

  

EXAMPLES:: 

  

sage: A = MatrixSpace(Integers(8),3)([1,7,3, 1,1,1, 3,4,5]) 

sage: A.det() 

6 

""" 

return self.determinant(*args, **kwds) 

  

def apply_morphism(self, phi): 

""" 

Apply the morphism phi to the coefficients of this dense matrix. 

  

The resulting matrix is over the codomain of phi. 

  

INPUT: 

  

  

- ``phi`` - a morphism, so phi is callable and 

phi.domain() and phi.codomain() are defined. The codomain must be a 

ring. 

  

OUTPUT: a matrix over the codomain of phi 

  

EXAMPLES:: 

  

sage: m = matrix(ZZ, 3, 3, range(9)) 

sage: phi = ZZ.hom(GF(5)) 

sage: m.apply_morphism(phi) 

[0 1 2] 

[3 4 0] 

[1 2 3] 

sage: parent(m.apply_morphism(phi)) 

Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 5 

  

We apply a morphism to a matrix over a polynomial ring:: 

  

sage: R.<x,y> = QQ[] 

sage: m = matrix(2, [x,x^2 + y, 2/3*y^2-x, x]); m 

[ x x^2 + y] 

[2/3*y^2 - x x] 

sage: phi = R.hom([y,x]) 

sage: m.apply_morphism(phi) 

[ y y^2 + x] 

[2/3*x^2 - y y] 

""" 

M = self.parent().change_ring(phi.codomain()) 

if self.is_sparse(): 

values = {(i,j): phi(z) for (i,j),z in self.dict()} 

else: 

values = [phi(z) for z in self.list()] 

image = M(values) 

if self._subdivisions is not None: 

image.subdivide(*self.subdivisions()) 

return image 

  

def apply_map(self, phi, R=None, sparse=None): 

""" 

Apply the given map phi (an arbitrary Python function or callable 

object) to this dense matrix. If R is not given, automatically 

determine the base ring of the resulting matrix. 

  

INPUT: 

  

- ``sparse`` -- True to make the output a sparse matrix; default False 

  

- ``phi`` - arbitrary Python function or callable object 

  

- ``R`` - (optional) ring 

  

OUTPUT: a matrix over R 

  

EXAMPLES:: 

  

sage: m = matrix(ZZ, 3, 3, range(9)) 

sage: k.<a> = GF(9) 

sage: f = lambda x: k(x) 

sage: n = m.apply_map(f); n 

[0 1 2] 

[0 1 2] 

[0 1 2] 

sage: n.parent() 

Full MatrixSpace of 3 by 3 dense matrices over Finite Field in a of size 3^2 

  

In this example, we explicitly specify the codomain. 

  

:: 

  

sage: s = GF(3) 

sage: f = lambda x: s(x) 

sage: n = m.apply_map(f, k); n 

[0 1 2] 

[0 1 2] 

[0 1 2] 

sage: n.parent() 

Full MatrixSpace of 3 by 3 dense matrices over Finite Field in a of size 3^2 

  

If self is subdivided, the result will be as well:: 

  

sage: m = matrix(2, 2, srange(4)) 

sage: m.subdivide(None, 1); m 

[0|1] 

[2|3] 

sage: m.apply_map(lambda x: x*x) 

[0|1] 

[4|9] 

  

If the matrix is sparse, the result will be as well:: 

  

sage: m = matrix(ZZ,100,100,sparse=True) 

sage: m[18,32] = -6 

sage: m[1,83] = 19 

sage: n = m.apply_map(abs, R=ZZ) 

sage: n.dict() 

{(1, 83): 19, (18, 32): 6} 

sage: n.is_sparse() 

True 

  

If the map sends most of the matrix to zero, then it may be useful 

to get the result as a sparse matrix. 

  

:: 

  

sage: m = matrix(ZZ, 3, 3, range(1, 10)) 

sage: n = m.apply_map(lambda x: 1//x, sparse=True); n 

[1 0 0] 

[0 0 0] 

[0 0 0] 

sage: n.parent() 

Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring 

  

TESTS:: 

  

sage: m = matrix([]) 

sage: m.apply_map(lambda x: x*x) == m 

True 

  

sage: m.apply_map(lambda x: x*x, sparse=True).parent() 

Full MatrixSpace of 0 by 0 sparse matrices over Integer Ring 

  

Check that :trac:`19920` is fixed:: 

  

sage: matrix.ones(2).apply_map(lambda x: int(-3)) 

[-3 -3] 

[-3 -3] 

""" 

if self._nrows == 0 or self._ncols == 0: 

if sparse is None or self.is_sparse() is sparse: 

return self.__copy__() 

elif sparse: 

return self.sparse_matrix() 

else: 

return self.dense_matrix() 

  

if self.is_sparse(): 

values = {(i,j): phi(v) for (i,j),v in self.dict().iteritems()} 

if R is None: 

R = sage.structure.sequence.Sequence(values.values()).universe() 

else: 

values = [phi(v) for v in self.list()] 

if R is None: 

R = sage.structure.sequence.Sequence(values).universe() 

  

if isinstance(R, type): 

R = py_scalar_parent(R) 

if not is_Ring(R): 

raise TypeError("unable to find a common ring for all elements") 

  

if sparse is None or sparse is self.is_sparse(): 

M = self.parent().change_ring(R) 

else: 

from sage.matrix.matrix_space import MatrixSpace 

M = MatrixSpace(R, self._nrows, 

self._ncols, sparse=sparse) 

image = M(values) 

if self._subdivisions is not None: 

image.subdivide(*self.subdivisions()) 

return image 

  

def characteristic_polynomial(self, *args, **kwds): 

""" 

Synonym for self.charpoly(...). 

  

EXAMPLES:: 

  

sage: a = matrix(QQ, 2,2, [1,2,3,4]); a 

[1 2] 

[3 4] 

sage: a.characteristic_polynomial('T') 

T^2 - 5*T - 2 

""" 

return self.charpoly(*args, **kwds) 

  

def minimal_polynomial(self, var='x', **kwds): 

r""" 

This is a synonym for ``self.minpoly`` 

  

EXAMPLES:: 

  

sage: a = matrix(QQ, 4, 4, range(16)) 

sage: a.minimal_polynomial('z') 

z^3 - 30*z^2 - 80*z 

sage: a.minpoly() 

x^3 - 30*x^2 - 80*x 

""" 

return self.minpoly(var, **kwds) 

  

def minpoly(self, var='x', **kwds): 

r""" 

Return the minimal polynomial of self. 

  

This uses a simplistic - and potentially very very slow - algorithm 

that involves computing kernels to determine the powers of the 

factors of the charpoly that divide the minpoly. 

  

EXAMPLES:: 

  

sage: A = matrix(GF(9,'c'), 4, [1, 1, 0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5]) 

sage: factor(A.minpoly()) 

(x + 1) * (x + 2)^2 

sage: A.minpoly()(A) == 0 

True 

sage: factor(A.charpoly()) 

(x + 1)^2 * (x + 2)^2 

  

The default variable name is `x`, but you can specify 

another name:: 

  

sage: factor(A.minpoly('y')) 

(y + 1) * (y + 2)^2 

  

""" 

f = self.fetch('minpoly') 

if not f is None: 

return f.change_variable_name(var) 

f = self.charpoly(var=var, **kwds) 

if f.is_squarefree(): # is_squarefree for polys much faster than factor. 

# Then f must be the minpoly 

self.cache('minpoly', f) 

return f 

  

# Now we have to work harder. We find the power of each 

# irreducible factor that divides the minpoly. 

mp = f.radical() 

for h, e in f.factor(): 

if e > 1: 

# Find the power of B so that the dimension 

# of the kernel equals e*deg(h) 

B = h(self) # this is the killer. 

C = B 

n = 1 

while C.kernel().dimension() < e*h.degree(): 

if n == e - 1: 

n += 1 

break 

C *= B 

n += 1 

mp *= h**(n-1) 

self.cache('minpoly', mp) 

return mp 

  

def charpoly(self, var = 'x', algorithm = None): 

r""" 

Returns the characteristic polynomial of self, as a polynomial over 

the base ring. 

  

ALGORITHM: 

  

In the generic case of matrices over a ring (commutative and with 

unity), there is a division-free algorithm, which can be accessed 

using ``"df"``, with complexity `O(n^4)`. Alternatively, by 

specifying ``"hessenberg"``, this method computes the Hessenberg 

form of the matrix and then reads off the characteristic polynomial. 

Moreover, for matrices over number fields, this method can use 

PARI's charpoly implementation instead. 

  

The method's logic is as follows: If no algorithm is specified, 

first check if the base ring is a number field (and then use PARI), 

otherwise check if the base ring is the ring of integers modulo n (in 

which case compute the characteristic polynomial of a lift of the 

matrix to the integers, and then coerce back to the base), next check 

if the base ring is an exact field (and then use the Hessenberg form), 

or otherwise, use the generic division-free algorithm. 

If an algorithm is specified explicitly, if 

``algorithm == "hessenberg"``, use the Hessenberg form, or otherwise 

use the generic division-free algorithm. 

  

The result is cached. 

  

INPUT: 

  

- ``var`` - a variable name (default: 'x') 

- ``algorithm`` - string: 

- ``"df"`` - Generic `O(n^4)` division-free algorithm 

- ``"hessenberg"`` - Use the Hessenberg form of the matrix 

  

EXAMPLES: 

  

First a matrix over `\ZZ`:: 

  

sage: A = MatrixSpace(ZZ,2)( [1,2, 3,4] ) 

sage: f = A.charpoly('x') 

sage: f 

x^2 - 5*x - 2 

sage: f.parent() 

Univariate Polynomial Ring in x over Integer Ring 

sage: f(A) 

[0 0] 

[0 0] 

  

An example over `\QQ`:: 

  

sage: A = MatrixSpace(QQ,3)(range(9)) 

sage: A.charpoly('x') 

x^3 - 12*x^2 - 18*x 

sage: A.trace() 

12 

sage: A.determinant() 

0 

  

We compute the characteristic polynomial of a matrix over the 

polynomial ring `\ZZ[a]`:: 

  

sage: R.<a> = PolynomialRing(ZZ) 

sage: M = MatrixSpace(R,2)([a,1, a,a+1]); M 

[ a 1] 

[ a a + 1] 

sage: f = M.charpoly('x'); f 

x^2 + (-2*a - 1)*x + a^2 

sage: f.parent() 

Univariate Polynomial Ring in x over Univariate Polynomial Ring in a over Integer Ring 

sage: M.trace() 

2*a + 1 

sage: M.determinant() 

a^2 

  

We compute the characteristic polynomial of a matrix over the 

multi-variate polynomial ring `\ZZ[x,y]`:: 

  

sage: R.<x,y> = PolynomialRing(ZZ,2) 

sage: A = MatrixSpace(R,2)([x, y, x^2, y^2]) 

sage: f = A.charpoly('x'); f 

x^2 + (-y^2 - x)*x - x^2*y + x*y^2 

  

It's a little difficult to distinguish the variables. To fix this, 

we temporarily view the indeterminate as `Z`:: 

  

sage: with localvars(f.parent(), 'Z'): print(f) 

Z^2 + (-y^2 - x)*Z - x^2*y + x*y^2 

  

We could also compute f in terms of Z from the start:: 

  

sage: A.charpoly('Z') 

Z^2 + (-y^2 - x)*Z - x^2*y + x*y^2 

  

Here is an example over a number field:: 

  

sage: x = QQ['x'].gen() 

sage: K.<a> = NumberField(x^2 - 2) 

sage: m = matrix(K, [[a-1, 2], [a, a+1]]) 

sage: m.charpoly('Z') 

Z^2 - 2*a*Z - 2*a + 1 

sage: m.charpoly('a')(m) == 0 

True 

  

Over integers modulo `n` with composite `n`:: 

  

sage: A = Mat(Integers(6),3,3)(range(9)) 

sage: A.charpoly() 

x^3 

  

Here is an example over a general commutative ring, that is to say, 

as of version 4.0.2, SAGE does not even positively determine that 

``S`` in the following example is an integral domain. But the 

computation of the characteristic polynomial succeeds as follows:: 

  

sage: R.<a,b> = QQ[] 

sage: S.<x,y> = R.quo((b^3)) 

sage: A = matrix(S, [[x*y^2,2*x],[2,x^10*y]]) 

sage: A 

[ x*y^2 2*x] 

[ 2 x^10*y] 

sage: A.charpoly('T') 

T^2 + (-x^10*y - x*y^2)*T - 4*x 

  

TESTS:: 

  

sage: P.<a,b,c> = PolynomialRing(Rationals()) 

sage: u = MatrixSpace(P,3)([[0,0,a],[1,0,b],[0,1,c]]) 

sage: Q.<x> = PolynomialRing(P) 

sage: u.charpoly('x') 

x^3 - c*x^2 - b*x - a 

  

A test case from :trac:`6442`. Prior to :trac:`12292`, the 

call to ``A.det()`` would attempt to use the cached charpoly, 

and crash if an empty dictionary was cached. We don't cache 

dictionaries anymore, but this test should still pass:: 

  

sage: z = Zp(p=5) 

sage: A = matrix(z, [ [3 + O(5^1), 4 + O(5^1), 4 + O(5^1)], 

....: [2*5^2 + O(5^3), 2 + O(5^1), 1 + O(5^1)], 

....: [5 + O(5^2), 1 + O(5^1), 1 + O(5^1)] ]) 

sage: A.charpoly(algorithm='hessenberg') 

Traceback (most recent call last): 

... 

ValueError: negative valuation 

sage: A.det() 

3 + O(5) 

  

The cached polynomial should be independent of the ``var`` 

argument (:trac:`12292`). We check (indirectly) that the 

second call uses the cached value by noting that its result is 

not cached:: 

  

sage: M = MatrixSpace(RR, 2) 

sage: A = M(range(2^2)) 

sage: type(A) 

<type 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'> 

sage: A.charpoly('x') 

x^2 - 3.00000000000000*x - 2.00000000000000 

sage: A.charpoly('y') 

y^2 - 3.00000000000000*y - 2.00000000000000 

sage: A._cache['charpoly'] 

x^2 - 3.00000000000000*x - 2.00000000000000 

  

AUTHORS: 

  

- Unknown: No author specified in the file from 2009-06-25 

- Sebastian Pancratz (2009-06-25): Include the division-free algorithm 

""" 

  

f = self.fetch('charpoly') 

if f is not None: 

return f.change_variable_name(var) 

  

from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing 

  

if algorithm is None: 

R = self._base_ring 

if is_NumberField(R): 

f = self._charpoly_over_number_field(var) 

elif is_IntegerModRing(R): 

f = self.lift().charpoly(var).change_ring(R) 

elif R.is_field(proof = False) and R.is_exact(): 

f = self._charpoly_hessenberg(var) 

else: 

f = self._charpoly_df(var) 

else: 

if algorithm == "hessenberg": 

f = self._charpoly_hessenberg(var) 

else: 

f = self._charpoly_df(var) 

  

# Cache the result, and return it. 

self.cache('charpoly', f) 

return f 

  

def _charpoly_df(self, var = 'x'): 

r""" 

Computes the characteristic polynomial of ``self`` without divisions. 

  

INPUT: 

  

- ``var`` - a variable name (default: ``'x'``) 

  

OUTPUT: 

  

- polynomial -- the characteristic polynomial of ``self`` 

  

EXAMPLES: 

  

Here is one easy example over the integers to illustrate this:: 

  

sage: A = matrix(ZZ, [[1,24],[3,5]]) 

sage: A 

[ 1 24] 

[ 3 5] 

sage: A._charpoly_df() 

x^2 - 6*x - 67 

  

The second example is a matrix over a univariate polynomial ring over the 

rationals:: 

  

sage: R.<t> = QQ[] 

sage: A = matrix(R, [[7*t^2 - t - 9, -1/4*t - 1, -17*t^2 - t + 1], \ 

[-t^2 + 1/4*t, t^2 + 5/7*t + 3, 1/5*t^2 + \ 

1662], \ 

[-2*t - 3, 2*t^2 + 6*t - 1/2, -1/6*t^2]]) 

sage: A 

[ 7*t^2 - t - 9 -1/4*t - 1 -17*t^2 - t + 1] 

[ -t^2 + 1/4*t t^2 + 5/7*t + 3 1/5*t^2 + 1662] 

[ -2*t - 3 2*t^2 + 6*t - 1/2 -1/6*t^2] 

sage: A._charpoly_df() 

x^3 + (-47/6*t^2 + 2/7*t + 6)*x^2 + (79/15*t^4 - 13189/420*t^3 - 

1884709/560*t^2 - 279501/28*t + 807)*x - 901/30*t^6 - 423/8*t^5 + 

11218517/480*t^4 + 2797765/42*t^3 - 12987971/280*t^2 - 5235245/56*t + 2484 

  

Thirdly, an example over a ring which is not an integral domain:: 

  

sage: A = matrix(ZZ.quo(12), 3, [5,8,0,10,2,1,8,7,9]) 

sage: A 

[ 5 8 0] 

[10 2 1] 

[ 8 7 9] 

sage: A._charpoly_df() 

x^3 + 8*x^2 + 10*x + 1 

  

TESTS:: 

  

sage: A = matrix(ZZ, 0, 0) 

sage: A 

[] 

sage: A._charpoly_df() 

1 

  

sage: A = matrix(ZZ, 1, 1, [[23]]) 

sage: A._charpoly_df() 

x - 23 

  

NOTES: 

  

The key feature of this implementation is that it is division-free. 

This means that it can be used as a generic implementation for any 

ring (commutative and with multiplicative identity). The algorithm 

is described in full detail as Algorithm 3.1 in [Se02]. 

  

Note that there is a missing minus sign in front of the last term in 

the penultimate line of Algorithm 3.1. 

  

REFERENCES: 

  

- [Se02] T. R. Seifullin, "Computation of determinants, adjoint 

matrices, and characteristic polynomials without division" 

  

AUTHORS: 

  

- Sebastian Pancratz (2009-06-12) 

""" 

  

# Validate assertions 

# 

if not self.is_square(): 

raise ValueError("self must be a square matrix") 

  

from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing 

  

# Extract parameters 

# 

cdef Matrix M = <Matrix> self 

n = M._ncols 

R = M._base_ring 

S = PolynomialRing(R, var) 

  

# Corner cases 

# N.B. We already tested for M to be square, hence we do not need to 

# test for 0 x n or m x 0 matrices. 

# 

if n == 0: 

return S(1) 

  

# In the notation of Algorithm 3.1, 

# 

# F Matrix over R such that F[p, t] is the coefficient of X^{t-p} 

# in the polynomial $F_t$; 

# a List of lists such that a[p, t] is a vector of length t; 

# A Matrix over R. 

# 

# But by looking at the algorithm, we see that in F, a and A we can 

# drop the second index t, reducing storage requirements. 

# 

# N.B. The documentation is still 1-based, although the code, after 

# having been ported from Magma to SAGE, is 0-based. 

# 

from sage.matrix.constructor import matrix 

  

F = [R(0) for i in xrange(n)] 

cdef Matrix a = <Matrix> matrix(R, n-1, n) 

A = [R(0) for i in xrange(n)] 

  

F[0] = - M.get_unsafe(0, 0) 

for t in xrange(1,n): 

  

# Set a(1, t) to be M(<=t, t) 

# 

for i in xrange(t+1): 

a.set_unsafe(0, i, M.get_unsafe(i, t)) 

  

# Set A[1, t] to be the (t)th entry in a[1, t] 

# 

A[0] = M.get_unsafe(t, t) 

  

for p in xrange(1, t): 

  

# Set a(p, t) to the product of M[<=t, <=t] * a(p-1, t) 

# 

for i in xrange(t+1): 

s = R(0) 

for j in xrange(t+1): 

s = s + M.get_unsafe(i, j) * a.get_unsafe(p-1, j) 

a.set_unsafe(p, i, s) 

  

# Set A[p, t] to be the (t)th entry in a[p, t] 

# 

A[p] = a.get_unsafe(p, t) 

  

# Set A[t, t] to be M[t, <=t] * a(p-1, t) 

# 

s = R(0) 

for j in xrange(t+1): 

s = s + M.get_unsafe(t, j) * a.get_unsafe(t-1, j) 

A[t] = s 

  

for p in xrange(t+1): 

s = F[p] 

for k in xrange(p): 

s = s - A[k] * F[p-k-1] 

F[p] = s - A[p] 

  

X = S.gen(0) 

f = X ** n 

for p in xrange(n): 

f = f + F[p] * X ** (n-1-p) 

  

return f 

  

def _charpoly_over_number_field(self, var='x'): 

r""" 

Use PARI to compute the characteristic polynomial of self as a 

polynomial over the base ring. 

  

EXAMPLES:: 

  

sage: x = QQ['x'].gen() 

sage: K.<a> = NumberField(x^2 - 2) 

sage: m = matrix(K, [[a-1, 2], [a, a+1]]) 

sage: m._charpoly_over_number_field('Z') 

Z^2 - 2*a*Z - 2*a + 1 

sage: m._charpoly_over_number_field('a')(m) == 0 

True 

sage: m = matrix(K, [[0, a, 0], [-a, 0, 0], [0, 0, 0]]) 

sage: m._charpoly_over_number_field('Z') 

Z^3 + 2*Z 

  

The remaining tests are indirect:: 

  

sage: L.<b> = K.extension(x^3 - a) 

sage: m = matrix(L, [[b+a, 1], [a, b^2-2]]) 

sage: m.charpoly('Z') 

Z^2 + (-b^2 - b - a + 2)*Z + a*b^2 - 2*b - 2*a 

sage: m.charpoly('a') 

a^2 + (-b^2 - b - a + 2)*a + a*b^2 - 2*b - 2*a 

sage: m.charpoly('a')(m) == 0 

True 

  

:: 

  

sage: M.<c> = L.extension(x^2 - a*x + b) 

sage: m = matrix(M, [[a+b+c, 0, b], [0, c, 1], [a-1, b^2+1, 2]]) 

sage: f = m.charpoly('Z'); f 

Z^3 + (-2*c - b - a - 2)*Z^2 + ((b + 2*a + 4)*c - b^2 + (-a + 2)*b + 2*a - 1)*Z + (b^2 + (a - 3)*b - 4*a + 1)*c + a*b^2 + 3*b + 2*a 

sage: f(m) == 0 

True 

sage: f.base_ring() is M 

True 

""" 

K = self.base_ring() 

if not is_NumberField(K): 

raise ValueError("_charpoly_over_number_field called with base ring (%s) not a number field" % K) 

  

paripoly = self.__pari__().charpoly() 

return K[var](paripoly) 

  

def fcp(self, var='x'): 

""" 

Return the factorization of the characteristic polynomial of self. 

  

INPUT: 

  

- ``var`` - (default: 'x') name of variable of charpoly 

  

EXAMPLES:: 

  

sage: M = MatrixSpace(QQ,3,3) 

sage: A = M([1,9,-7,4/5,4,3,6,4,3]) 

sage: A.fcp() 

x^3 - 8*x^2 + 209/5*x - 286 

sage: A = M([3, 0, -2, 0, -2, 0, 0, 0, 0]) 

sage: A.fcp('T') 

(T - 3) * T * (T + 2) 

""" 

return self.charpoly(var).factor() 

  

def denominator(self): 

r""" 

Return the least common multiple of the denominators of the 

elements of self. 

  

If there is no denominator function for the base field, or no LCM 

function for the denominators, raise a TypeError. 

  

EXAMPLES:: 

  

sage: A = MatrixSpace(QQ,2)([1/2, 1/3, 1/5, 1/7]) 

sage: A.denominator() 

210 

  

A trivial example:: 

  

sage: A = matrix(QQ, 0,2) 

sage: A.denominator() 

1 

  

Denominators are not defined for real numbers:: 

  

sage: A = MatrixSpace(RealField(),2)([1,2,3,4]) 

sage: A.denominator() 

Traceback (most recent call last): 

... 

TypeError: denominator not defined for elements of the base ring 

  

We can even compute the denominator of matrix over the fraction 

field of `\ZZ[x]`. 

  

:: 

  

sage: K.<x> = Frac(ZZ['x']) 

sage: A = MatrixSpace(K,2)([1/x, 2/(x+1), 1, 5/(x^3)]) 

sage: A.denominator() 

x^4 + x^3 

  

Here's an example involving a cyclotomic field:: 

  

sage: K.<z> = CyclotomicField(3) 

sage: M = MatrixSpace(K,3,sparse=True) 

sage: A = M([(1+z)/3,(2+z)/3,z/3,1,1+z,-2,1,5,-1+z]) 

sage: print(A) 

[1/3*z + 1/3 1/3*z + 2/3 1/3*z] 

[ 1 z + 1 -2] 

[ 1 5 z - 1] 

sage: print(A.denominator()) 

3 

""" 

if self.nrows() == 0 or self.ncols() == 0: 

return ZZ(1) 

R = self.base_ring() 

x = self.list() 

try: 

d = x[0].denominator() 

except AttributeError: 

raise TypeError("denominator not defined for elements of the base ring") 

try: 

for y in x: 

d = d.lcm(y.denominator()) 

except AttributeError: 

raise TypeError("lcm function not defined for elements of the base ring") 

return d 

  

def diagonal(self): 

r""" 

Return the diagonal entries of ``self``. 

  

OUTPUT: 

  

A list containing the entries of the matrix that 

have equal row and column indices, in order of the 

indices. Behavior is not limited to square matrices. 

  

EXAMPLES:: 

  

sage: A = matrix([[2,5],[3,7]]); A 

[2 5] 

[3 7] 

sage: A.diagonal() 

[2, 7] 

  

Two rectangular matrices. :: 

  

sage: B = matrix(3, 7, range(21)); B 

[ 0 1 2 3 4 5 6] 

[ 7 8 9 10 11 12 13] 

[14 15 16 17 18 19 20] 

sage: B.diagonal() 

[0, 8, 16] 

  

sage: C = matrix(3, 2, range(6)); C 

[0 1] 

[2 3] 

[4 5] 

sage: C.diagonal() 

[0, 3] 

  

Empty matrices behave properly. :: 

  

sage: E = matrix(0, 5, []); E 

[] 

sage: E.diagonal() 

[] 

""" 

n = min(self.nrows(), self.ncols()) 

return [self[i,i] for i in range(n)] 

  

def trace(self): 

""" 

Return the trace of self, which is the sum of the diagonal entries 

of self. 

  

INPUT: 

  

  

- ``self`` - a square matrix 

  

  

OUTPUT: element of the base ring of self 

  

EXAMPLES:: 

  

sage: a = matrix(3,3,range(9)); a 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: a.trace() 

12 

sage: a = matrix({(1,1):10, (2,1):-3, (2,2):4/3}); a 

[ 0 0 0] 

[ 0 10 0] 

[ 0 -3 4/3] 

sage: a.trace() 

34/3 

""" 

if self._nrows != self._ncols: 

raise ValueError("self must be a square matrix") 

R = self._base_ring 

cdef Py_ssize_t i 

cdef object s 

s = R(0) 

for i from 0 <= i < self._nrows: 

s = s + self.get_unsafe(i,i) 

return s 

  

def trace_of_product(self, Matrix other): 

""" 

Returns the trace of self * other without computing the entire product. 

  

EXAMPLES:: 

  

sage: M = random_matrix(ZZ, 10, 20) 

sage: N = random_matrix(ZZ, 20, 10) 

sage: M.trace_of_product(N) 

-1629 

sage: (M*N).trace() 

-1629 

""" 

if self._nrows != other._ncols or other._nrows != self._ncols: 

raise ArithmeticError("incompatible dimensions") 

s = self._base_ring(0) 

for i from 0 <= i < self._nrows: 

for j from 0 <= j < self._ncols: 

s += self.get_unsafe(i, j) * other.get_unsafe(j, i) 

return s 

  

##################################################################################### 

# Generic Hessenberg Form and charpoly algorithm 

##################################################################################### 

def hessenberg_form(self): 

""" 

Return Hessenberg form of self. 

  

If the base ring is merely an integral domain (and not a field), 

the Hessenberg form will (in general) only be defined over the 

fraction field of the base ring. 

  

EXAMPLES:: 

  

sage: A = matrix(ZZ,4,[2, 1, 1, -2, 2, 2, -1, -1, -1,1,2,3,4,5,6,7]) 

sage: h = A.hessenberg_form(); h 

[ 2 -7/2 -19/5 -2] 

[ 2 1/2 -17/5 -1] 

[ 0 25/4 15/2 5/2] 

[ 0 0 58/5 3] 

sage: parent(h) 

Full MatrixSpace of 4 by 4 dense matrices over Rational Field 

sage: A.hessenbergize() 

Traceback (most recent call last): 

... 

TypeError: Hessenbergize only possible for matrices over a field 

""" 

X = self.fetch('hessenberg_form') 

if not X is None: 

return X 

R = self._base_ring 

if not R.is_field(): 

try: 

K = self._base_ring.fraction_field() 

H = self.change_ring(K) 

H.hessenbergize() 

except TypeError as msg: 

raise TypeError("%s\nHessenberg form only possible for matrices over a field"%msg) 

else: 

H = self.__copy__() 

H.hessenbergize() 

#end if 

self.cache('hessenberg_form', H) 

return H 

  

def hessenbergize(self): 

""" 

Transform self to Hessenberg form. 

  

The hessenberg form of a matrix `A` is a matrix that is 

similar to `A`, so has the same characteristic polynomial 

as `A`, and is upper triangular except possible for entries 

right below the diagonal. 

  

ALGORITHM: See Henri Cohen's first book. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ,3, [2, 1, 1, -2, 2, 2, -1, -1, -1]) 

sage: A.hessenbergize(); A 

[ 2 3/2 1] 

[ -2 3 2] 

[ 0 -3 -2] 

  

:: 

  

sage: A = matrix(QQ,4, [2, 1, 1, -2, 2, 2, -1, -1, -1,1,2,3,4,5,6,7]) 

sage: A.hessenbergize(); A 

[ 2 -7/2 -19/5 -2] 

[ 2 1/2 -17/5 -1] 

[ 0 25/4 15/2 5/2] 

[ 0 0 58/5 3] 

  

You can't Hessenbergize an immutable matrix:: 

  

sage: A = matrix(QQ, 3, [1..9]) 

sage: A.set_immutable() 

sage: A.hessenbergize() 

Traceback (most recent call last): 

... 

ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M). 

""" 

cdef Py_ssize_t i, j, m, n, r 

n = self._nrows 

  

tm = verbose("Computing Hessenberg Normal Form of %sx%s matrix"%(n,n)) 

  

if not self.is_square(): 

raise TypeError("self must be square") 

  

if not self._base_ring.is_field(): 

raise TypeError("Hessenbergize only possible for matrices over a field") 

  

self.check_mutability() 

  

zero = self._base_ring(0) 

one = self._base_ring(1) 

for m from 1 <= m < n-1: 

# Search for a non-zero entry in column m-1 

i = -1 

for r from m+1 <= r < n: 

if self.get_unsafe(r, m-1) != zero: 

i = r 

break 

if i != -1: 

# Found a nonzero entry in column m-1 that is strictly below row m 

# Now set i to be the first nonzero position >= m in column m-1 

if self.get_unsafe(m,m-1) != zero: 

i = m 

t = self.get_unsafe(i,m-1) 

t_inv = None 

if i > m: 

self.swap_rows_c(i,m) 

# We must do the corresponding column swap to 

# maintain the characteristic polynomial (which is 

# an invariant of Hessenberg form) 

self.swap_columns_c(i,m) 

# Now the nonzero entry in position (m,m-1) is t. 

# Use t to clear the entries in column m-1 below m. 

for j from m+1 <= j < n: 

x = self.get_unsafe(j, m-1) 

if x != zero: 

if t_inv is None: 

t_inv = one / t 

u = x * t_inv 

self.add_multiple_of_row_c(j, m, -u, 0) 

# To maintain charpoly, do the corresponding column operation, 

# which doesn't mess up the matrix, since it only changes 

# column m, and we're only worried about column m-1 right now. 

# Add u*column_j to column_m. 

self.add_multiple_of_column_c(m, j, u, 0) 

verbose("Finished Hessenberg Normal Form of %sx%s matrix"%(n,n),tm) 

  

def _charpoly_hessenberg(self, var): 

""" 

Transforms self in place to its Hessenberg form then computes and 

returns the coefficients of the characteristic polynomial of this 

matrix. 

  

INPUT: 

  

- ``var`` - name of the indeterminate of the charpoly 

  

The characteristic polynomial is represented as a vector of ints, 

where the constant term of the characteristic polynomial is the 0th 

coefficient of the vector. 

  

EXAMPLES:: 

  

sage: matrix(QQ,3,3,range(9))._charpoly_hessenberg('Z') 

Z^3 - 12*Z^2 - 18*Z 

sage: matrix(ZZ,3,3,range(9))._charpoly_hessenberg('Z') 

Z^3 - 12*Z^2 - 18*Z 

sage: matrix(GF(7),3,3,range(9))._charpoly_hessenberg('Z') 

Z^3 + 2*Z^2 + 3*Z 

sage: matrix(QQ['x'],3,3,range(9))._charpoly_hessenberg('Z') 

Z^3 - 12*Z^2 - 18*Z 

sage: matrix(ZZ['ZZ'],3,3,range(9))._charpoly_hessenberg('Z') 

Z^3 - 12*Z^2 - 18*Z 

""" 

if self._nrows != self._ncols: 

raise ArithmeticError("charpoly not defined for non-square matrix.") 

  

# Replace self by its Hessenberg form 

# (note the entries might now live in the fraction field) 

cdef Matrix H 

H = self.hessenberg_form() 

  

# We represent the intermediate polynomials that come up in 

# the calculations as rows of an (n+1)x(n+1) matrix, since 

# we've implemented basic arithmetic with such a matrix. 

# Please see the generic implementation of charpoly in 

# matrix.py to see more clearly how the following algorithm 

# actually works. (The implementation is clearer (but slower) 

# if one uses polynomials to represent polynomials instead of 

# using the rows of a matrix.) Also see Cohen's first GTM, 

# Algorithm 2.2.9. 

  

cdef Py_ssize_t i, m, n, 

n = self._nrows 

  

cdef Matrix c 

c = H.new_matrix(nrows=n+1,ncols=n+1) # the 0 matrix 

one = H._coerce_element(1) 

c.set_unsafe(0,0,one) 

  

for m from 1 <= m <= n: 

# Set the m-th row of c to (x - H[m-1,m-1])*c[m-1] = x*c[m-1] - H[m-1,m-1]*c[m-1] 

# We do this by hand by setting the m-th row to c[m-1] 

# shifted to the right by one. We then add 

# -H[m-1,m-1]*c[m-1] to the resulting m-th row. 

for i from 1 <= i <= n: 

c.set_unsafe(m, i, c.get_unsafe(m-1,i-1)) 

c.add_multiple_of_row_c(m, m-1, -H.get_unsafe(m-1, m-1), 0) 

t = one 

for i from 1 <= i < m: 

t = t * H.get_unsafe(m-i,m-i-1) 

# Set the m-th row of c to c[m] - t*H[m-i-1,m-1]*c[m-i-1] 

c.add_multiple_of_row_c(m, m-i-1, - t*H.get_unsafe(m-i-1,m-1), 0) 

  

# The answer is now the n-th row of c. 

v = PyList_New(n+1) # this is really sort of v = []..." 

for i from 0 <= i <= n: 

# Finally, set v[i] = c[n,i] 

o = c.get_unsafe(n,i) 

Py_INCREF(o); PyList_SET_ITEM(v, i, o) 

  

R = self._base_ring[var] # polynomial ring over the base ring 

return R(v) 

  

##################################################################################### 

# Decomposition: kernel, image, decomposition 

##################################################################################### 

nullity = left_nullity 

  

def left_nullity(self): 

""" 

Return the (left) nullity of this matrix, which is the dimension of 

the (left) kernel of this matrix acting from the right on row 

vectors. 

  

EXAMPLES:: 

  

sage: M = Matrix(QQ,[[1,0,0,1],[0,1,1,0],[1,1,1,0]]) 

sage: M.nullity() 

0 

sage: M.left_nullity() 

0 

  

:: 

  

sage: A = M.transpose() 

sage: A.nullity() 

1 

sage: A.left_nullity() 

1 

  

:: 

  

sage: M = M.change_ring(ZZ) 

sage: M.nullity() 

0 

sage: A = M.transpose() 

sage: A.nullity() 

1 

""" 

# Use that rank + nullity = number of rows, since matrices act 

# from the right on row vectors. 

return self.nrows() - self.rank() 

  

def right_nullity(self): 

""" 

Return the right nullity of this matrix, which is the dimension of 

the right kernel. 

  

EXAMPLES:: 

  

sage: A = MatrixSpace(QQ,3,2)(range(6)) 

sage: A.right_nullity() 

0 

  

:: 

  

sage: A = matrix(ZZ,3,3,range(9)) 

sage: A.right_nullity() 

1 

""" 

return self.ncols() - self.rank() 

  

###################################### 

# Kernel Helper Functions 

###################################### 

  

def _right_kernel_matrix_over_number_field(self): 

r""" 

Returns a pair that includes a matrix of basis vectors 

for the right kernel of ``self``. 

  

OUTPUT: 

  

Returns a pair. First item is the string 'pivot-pari-numberfield' 

that identifies the nature of the basis vectors. 

  

Second item is a matrix whose rows are a basis for the right kernel, 

over the number field, as computed by PARI. 

  

EXAMPLES:: 

  

sage: Q = QuadraticField(-7) 

sage: a = Q.gen(0) 

sage: A = matrix(Q, [[ 2, 5-a, 15-a], 

....: [2+a, a, -7 + 5*a]]) 

sage: result = A._right_kernel_matrix_over_number_field() 

sage: result[0] 

'pivot-pari-numberfield' 

sage: P = result[1]; P 

[-a -3 1] 

sage: A*P.transpose() == zero_matrix(Q, 2, 1) 

True 

  

TESTS: 

  

We test some trivial cases. :: 

  

sage: Q = QuadraticField(-7) 

sage: A = matrix(Q, 0, 2) 

sage: A._right_kernel_matrix_over_number_field()[1] 

[1 0] 

[0 1] 

sage: A = matrix(Q, 2, 0) 

sage: A._right_kernel_matrix_over_number_field()[1].parent() 

Full MatrixSpace of 0 by 0 dense matrices over Number Field in a with defining polynomial x^2 + 7 

sage: A = zero_matrix(Q, 4, 3) 

sage: A._right_kernel_matrix_over_number_field()[1] 

[1 0 0] 

[0 1 0] 

[0 0 1] 

""" 

from sage.matrix.matrix_space import MatrixSpace 

tm = verbose("computing right kernel matrix over a number field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1) 

basis = self.__pari__().matker() 

# Coerce PARI representations into the number field 

R = self.base_ring() 

basis = [[R(x) for x in row] for row in basis] 

verbose("done computing right kernel matrix over a number field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm) 

return 'pivot-pari-numberfield', MatrixSpace(R, len(basis), ncols=self._ncols)(basis) 

  

def _right_kernel_matrix_over_field(self, *args, **kwds): 

r""" 

Returns a pair that includes a matrix of basis vectors 

for the right kernel of ``self``. 

  

OUTPUT: 

  

Returns a pair. First item is the string 'pivot-generic' 

that identifies the nature of the basis vectors. 

  

Second item is a matrix whose rows are a basis for the right kernel, 

over the field, as computed by general Python code. 

  

EXAMPLES:: 

  

sage: C = CyclotomicField(14) 

sage: a = C.gen(0) 

sage: A = matrix(C, 3, 4, [[ 1, a, 1+a, a^3+a^5], 

....: [ a, a^4, a+a^4, a^4+a^8], 

....: [a^2, a^6, a^2+a^6, a^5+a^10]]) 

sage: result = A._right_kernel_matrix_over_field() 

sage: result[0] 

'pivot-generic' 

sage: P = result[1]; P 

[ -1 -1 1 0] 

[-zeta14^3 -zeta14^4 0 1] 

sage: A*P.transpose() == zero_matrix(C, 3, 2) 

True 

  

TESTS: 

  

We test some trivial cases. :: 

  

sage: C = CyclotomicField(14) 

sage: A = matrix(C, 0, 2) 

sage: A._right_kernel_matrix_over_field()[1] 

[1 0] 

[0 1] 

sage: A = matrix(C, 2, 0) 

sage: A._right_kernel_matrix_over_field()[1].parent() 

Full MatrixSpace of 0 by 0 dense matrices over Cyclotomic Field of order 14 and degree 6 

sage: A = zero_matrix(C, 4, 3) 

sage: A._right_kernel_matrix_over_field()[1] 

[1 0 0] 

[0 1 0] 

[0 0 1] 

""" 

from sage.matrix.matrix_space import MatrixSpace 

tm = verbose("computing right kernel matrix over an arbitrary field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1) 

E = self.echelon_form(*args, **kwds) 

pivots = E.pivots() 

pivots_set = set(pivots) 

R = self.base_ring() 

zero = R(0) 

one = R(1) 

basis = [] 

for i in xrange(self._ncols): 

if not (i in pivots_set): 

v = [zero]*self._ncols 

v[i] = one 

for r in range(len(pivots)): 

v[pivots[r]] = -E[r,i] 

basis.append(v) 

tm = verbose("done computing right kernel matrix over an arbitrary field for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm) 

return 'pivot-generic', MatrixSpace(R, len(basis), self._ncols)(basis) 

  

def _right_kernel_matrix_over_domain(self): 

r""" 

Returns a pair that includes a matrix of basis vectors 

for the right kernel of ``self``. 

  

OUTPUT: 

  

Returns a pair. First item is the string 'computed-smith-form' 

that identifies the nature of the basis vectors. 

  

Second item is a matrix whose rows are a basis for the right kernel, 

over the field, as computed by general Python code. 

  

.. warning:: 

  

This routine uses Smith normal form, which can fail 

if the domain is not a principal ideal domain. Since we do 

not have a good test for PIDs, this is just a risk we take. 

See an example failure in the documentation for 

:meth:`right_kernel_matrix`. 

  

EXAMPLES: 

  

Univariate polynomials over a field form a PID. :: 

  

sage: R.<y> = QQ[] 

sage: A = matrix(R, [[ 1, y, 1+y^2], 

....: [y^3, y^2, 2*y^3]]) 

sage: result = A._right_kernel_matrix_over_domain() 

sage: result[0] 

'computed-smith-form' 

sage: P = result[1]; P 

[-1 -y 1] 

sage: A*P.transpose() == zero_matrix(R, 2, 1) 

True 

  

TESTS: 

  

We test some trivial cases. :: 

  

sage: R.<y> = QQ[] 

sage: A = matrix(R, 0, 2) 

sage: A._right_kernel_matrix_over_domain()[1] 

[1 0] 

[0 1] 

sage: A = matrix(R, 2, 0) 

sage: A._right_kernel_matrix_over_domain()[1].parent() 

Full MatrixSpace of 0 by 0 dense matrices over Univariate Polynomial Ring in y over Rational Field 

sage: A = zero_matrix(R, 4, 3) 

sage: A._right_kernel_matrix_over_domain()[1] 

[1 0 0] 

[0 1 0] 

[0 0 1] 

""" 

tm = verbose("computing right kernel matrix over a domain for %sx%s matrix" % (self.nrows(), self.ncols()),level=1) 

d, u, v = self.smith_form() 

basis = [] 

for i in xrange(self.ncols()): 

if (i >= self.nrows()) or d[i][i] == 0: 

basis.append( v.column(i).list() ) 

verbose("done computing right kernel matrix over a domain for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm) 

return 'computed-smith-form', self.new_matrix(nrows=len(basis), ncols=self._ncols, entries=basis) 

  

def right_kernel_matrix(self, *args, **kwds): 

r""" 

Returns a matrix whose rows form a basis 

for the right kernel of ``self``. 

  

INPUT: 

  

- ``algorithm`` - default: 'default' - a keyword that selects the 

algorithm employed. Allowable values are: 

  

- 'default' - allows the algorithm to be chosen automatically 

- 'generic' - naive algorithm usable for matrices over any field 

- 'flint' - FLINT library code for matrices over the rationals 

or the integers 

- 'pari' - PARI library code for matrices over number fields 

or the integers 

- 'padic' - padic algorithm from IML library for matrices 

over the rationals and integers 

- 'pluq' - PLUQ matrix factorization for matrices mod 2 

  

- ``basis`` - default: 'echelon' - a keyword that describes 

the format of the basis returned. Allowable values are: 

  

- 'echelon': the basis matrix is returned in echelon form 

- 'pivot' : each basis vector is computed from the reduced 

row-echelon form of ``self`` by placing a single one in a 

non-pivot column and zeros in the remaining non-pivot columns. 

Only available for matrices over fields. 

- 'LLL': an LLL-reduced basis. Only available for matrices 

over the integers. 

- 'computed': no work is done to transform the basis, it is 

returned exactly as provided by whichever routine actually 

computed the basis. Request this for the least possible 

computation possible, but with no guarantees about the format 

of the basis. 

  

OUTPUT: 

  

A matrix ``X`` whose rows are an independent set spanning the 

right kernel of ``self``. So ``self*X.transpose()`` is a zero matrix. 

  

The output varies depending on the choice of ``algorithm`` and the 

format chosen by ``basis``. 

  

The results of this routine are not cached, so you can call it again 

with different options to get possibly different output (like the basis 

format). Conversely, repeated calls on the same matrix will always 

start from scratch. 

  

.. NOTE:: 

  

If you want to get the most basic description of a kernel, with a 

minimum of overhead, then ask for the right kernel matrix with 

the basis format requested as 'computed'. You are then free to 

work with the output for whatever purpose. For a left kernel, 

call this method on the transpose of your matrix. 

  

For greater convenience, plus cached results, request an actual 

vector space or free module with :meth:`right_kernel` 

or :meth:`left_kernel`. 

  

EXAMPLES: 

  

Over the Rational Numbers: 

  

Kernels are computed by the IML library in 

:meth:`~sage.matrix.matrix_rational_dense.Matrix_rational_dense._right_kernel_matrix`. 

Setting the `algorithm` keyword to 'default', 'padic' or unspecified 

will yield the same result, as there is no optional behavior. 

The 'computed' format of the basis vectors are exactly the negatives 

of the vectors in the 'pivot' format. :: 

  

sage: A = matrix(QQ, [[1, 0, 1, -3, 1], 

....: [-5, 1, 0, 7, -3], 

....: [0, -1, -4, 6, -2], 

....: [4, -1, 0, -6, 2]]) 

sage: C = A.right_kernel_matrix(algorithm='default', basis='computed'); C 

[-1 2 -2 -1 0] 

[ 1 2 0 0 -1] 

sage: A*C.transpose() == zero_matrix(QQ, 4, 2) 

True 

sage: P = A.right_kernel_matrix(algorithm='padic', basis='pivot'); P 

[ 1 -2 2 1 0] 

[-1 -2 0 0 1] 

sage: A*P.transpose() == zero_matrix(QQ, 4, 2) 

True 

sage: C == -P 

True 

sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E 

[ 1 0 1 1/2 -1/2] 

[ 0 1 -1/2 -1/4 -1/4] 

sage: A*E.transpose() == zero_matrix(QQ, 4, 2) 

True 

  

Since the rationals are a field, we can call the general code 

available for any field by using the 'generic' keyword. :: 

  

sage: A = matrix(QQ, [[1, 0, 1, -3, 1], 

....: [-5, 1, 0, 7, -3], 

....: [0, -1, -4, 6, -2], 

....: [4, -1, 0, -6, 2]]) 

sage: G = A.right_kernel_matrix(algorithm='generic', basis='echelon'); G 

[ 1 0 1 1/2 -1/2] 

[ 0 1 -1/2 -1/4 -1/4] 

sage: A*G.transpose() == zero_matrix(QQ, 4, 2) 

True 

  

We verify that the rational matrix code is called for both 

dense and sparse rational matrices, with equal result. :: 

  

sage: A = matrix(QQ, [[1, 0, 1, -3, 1], 

....: [-5, 1, 0, 7, -3], 

....: [0, -1, -4, 6, -2], 

....: [4, -1, 0, -6, 2]], 

....: sparse=False) 

sage: B = copy(A).sparse_matrix() 

sage: set_verbose(1) 

sage: D = A.right_kernel(); D 

verbose 1 (<module>) computing a right kernel for 4x5 matrix over Rational Field 

... 

Vector space of degree 5 and dimension 2 over Rational Field 

Basis matrix: 

[ 1 0 1 1/2 -1/2] 

[ 0 1 -1/2 -1/4 -1/4] 

sage: S = B.right_kernel(); S 

verbose 1 (<module>) computing a right kernel for 4x5 matrix over Rational Field 

... 

Vector space of degree 5 and dimension 2 over Rational Field 

Basis matrix: 

[ 1 0 1 1/2 -1/2] 

[ 0 1 -1/2 -1/4 -1/4] 

sage: set_verbose(0) 

sage: D == S 

True 

  

Over Number Fields: 

  

Kernels are by default computed by PARI, (except for exceptions like 

the rationals themselves). The raw results from PARI are a pivot 

basis, so the `basis` keywords 'computed' and 'pivot' will return 

the same results. :: 

  

sage: Q = QuadraticField(-7) 

sage: a = Q.gen(0) 

sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a], 

....: [2+a, a, -7 + 5*a, -3+3*a]]) 

sage: C = A.right_kernel_matrix(algorithm='default', basis='computed'); C 

[ -a -3 1 0] 

[ -2 -a - 1 0 1] 

sage: A*C.transpose() == zero_matrix(Q, 2, 2) 

True 

sage: P = A.right_kernel_matrix(algorithm='pari', basis='pivot'); P 

[ -a -3 1 0] 

[ -2 -a - 1 0 1] 

sage: A*P.transpose() == zero_matrix(Q, 2, 2) 

True 

sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E 

[ 1 0 7/88*a + 3/88 -3/176*a - 39/176] 

[ 0 1 -1/88*a - 13/88 13/176*a - 7/176] 

sage: A*E.transpose() == zero_matrix(Q, 2, 2) 

True 

  

We can bypass using PARI for number fields and use Sage's general 

code for matrices over any field. The basis vectors as computed 

are in pivot format. :: 

  

sage: Q = QuadraticField(-7) 

sage: a = Q.gen(0) 

sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a],[2+a, a, -7 + 5*a, -3+3*a]]) 

sage: G = A.right_kernel_matrix(algorithm='generic', basis='computed'); G 

[ -a -3 1 0] 

[ -2 -a - 1 0 1] 

sage: A*G.transpose() == zero_matrix(Q, 2, 2) 

True 

  

We check that number fields are handled by the right routine as part of 

typical right kernel computation. :: 

  

sage: Q = QuadraticField(-7) 

sage: a = Q.gen(0) 

sage: A = matrix(Q, [[2, 5-a, 15-a, 16+4*a],[2+a, a, -7 + 5*a, -3+3*a]]) 

sage: set_verbose(1) 

sage: A.right_kernel(algorithm='default') 

verbose ... 

verbose 1 (<module>) computing right kernel matrix over a number field for 2x4 matrix 

verbose 1 (<module>) done computing right kernel matrix over a number field for 2x4 matrix 

... 

Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7 

Basis matrix: 

[ 1 0 7/88*a + 3/88 -3/176*a - 39/176] 

[ 0 1 -1/88*a - 13/88 13/176*a - 7/176] 

sage: set_verbose(0) 

  

Over the Finite Field of Order 2: 

  

Kernels are computed by the M4RI library using PLUQ matrix 

decomposition in the 

:meth:`~sage.matrix.matrix_mod2_dense.Matrix_mod2_dense._right_kernel_matrix` 

method. There are no options for the algorithm used. :: 

  

sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0], 

....: [1, 0, 0, 0, 1, 1,], 

....: [1, 0, 0, 0, 1, 1]]) 

sage: E = A.right_kernel_matrix(algorithm='default', format='echelon'); E 

[1 0 0 0 0 1] 

[0 1 1 0 0 0] 

[0 0 0 1 0 0] 

[0 0 0 0 1 1] 

sage: A*E.transpose() == zero_matrix(GF(2), 3, 4) 

True 

  

Since GF(2) is a field we can route this computation to the generic 

code and obtain the 'pivot' form of the basis. The ``algorithm`` 

keywords, 'pluq', 'default' and unspecified, all have the 

same effect as there is no optional behavior. :: 

  

sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0], 

....: [1, 0, 0, 0, 1, 1,], 

....: [1, 0, 0, 0, 1, 1]]) 

sage: P = A.right_kernel_matrix(algorithm='generic', basis='pivot'); P 

[0 1 1 0 0 0] 

[0 0 0 1 0 0] 

[1 0 0 0 1 0] 

[1 0 0 0 0 1] 

sage: A*P.transpose() == zero_matrix(GF(2), 3, 4) 

True 

sage: DP = A.right_kernel_matrix(algorithm='default', basis='pivot'); DP 

[0 1 1 0 0 0] 

[0 0 0 1 0 0] 

[1 0 0 0 1 0] 

[1 0 0 0 0 1] 

sage: A*DP.transpose() == zero_matrix(GF(2), 3, 4) 

True 

sage: A.right_kernel_matrix(algorithm='pluq', basis='echelon') 

[1 0 0 0 0 1] 

[0 1 1 0 0 0] 

[0 0 0 1 0 0] 

[0 0 0 0 1 1] 

  

We test that the mod 2 code is called for matrices over GF(2). :: 

  

sage: A = matrix(GF(2),[[0, 1, 1, 0, 0, 0], 

....: [1, 0, 0, 0, 1, 1,], 

....: [1, 0, 0, 0, 1, 1]]) 

sage: set_verbose(1) 

sage: A.right_kernel(algorithm='default') 

verbose ... 

verbose 1 (<module>) computing right kernel matrix over integers mod 2 for 3x6 matrix 

verbose 1 (<module>) done computing right kernel matrix over integers mod 2 for 3x6 matrix 

... 

Vector space of degree 6 and dimension 4 over Finite Field of size 2 

Basis matrix: 

[1 0 0 0 0 1] 

[0 1 1 0 0 0] 

[0 0 0 1 0 0] 

[0 0 0 0 1 1] 

sage: set_verbose(0) 

  

Over Arbitrary Fields: 

  

For kernels over fields not listed above, totally general code 

will compute a set of basis vectors in the pivot format. 

These could be returned as a basis in echelon form. :: 

  

sage: F.<a> = FiniteField(5^2) 

sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5], 

....: [ a, a^4, a+a^4, a^4+a^8], 

....: [a^2, a^6, a^2+a^6, a^5+a^10]]) 

sage: P = A.right_kernel_matrix(algorithm='default', basis='pivot'); P 

[ 4 4 1 0] 

[ a + 2 3*a + 3 0 1] 

sage: A*P.transpose() == zero_matrix(F, 3, 2) 

True 

sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E 

[ 1 0 3*a + 4 2*a + 2] 

[ 0 1 2*a 3*a + 3] 

sage: A*E.transpose() == zero_matrix(F, 3, 2) 

True 

  

This general code can be requested for matrices over any field 

with the ``algorithm`` keyword 'generic'. Normally, matrices 

over the rationals would be handled by specific routines from 

the IML library. The default format is an echelon basis, but a 

pivot basis may be requested, which is identical to the computed 

basis. :: 

  

sage: A = matrix(QQ, 3, 4, [[1,3,-2,4], 

....: [2,0,2,2], 

....: [-1,1,-2,0]]) 

sage: G = A.right_kernel_matrix(algorithm='generic'); G 

[ 1 0 -1/2 -1/2] 

[ 0 1 1/2 -1/2] 

sage: A*G.transpose() == zero_matrix(QQ, 3, 2) 

True 

sage: C = A.right_kernel_matrix(algorithm='generic', basis='computed'); C 

[-1 1 1 0] 

[-1 -1 0 1] 

sage: A*C.transpose() == zero_matrix(QQ, 3, 2) 

True 

  

We test that the generic code is called for matrices over fields, 

lacking any more specific routine. :: 

  

sage: F.<a> = FiniteField(5^2) 

sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5], 

....: [ a, a^4, a+a^4, a^4+a^8], 

....: [a^2, a^6, a^2+a^6, a^5+a^10]]) 

sage: set_verbose(1) 

sage: A.right_kernel(algorithm='default') 

verbose ... 

verbose 1 (<module>) computing right kernel matrix over an arbitrary field for 3x4 matrix 

... 

Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2 

Basis matrix: 

[ 1 0 3*a + 4 2*a + 2] 

[ 0 1 2*a 3*a + 3] 

sage: set_verbose(0) 

  

Over the Integers: 

  

Either the IML or PARI libraries are used to provide a set of basis 

vectors. The ``algorithm`` keyword can be used to select either, 

or when set to 'default' a heuristic will choose between the two. 

Results can be returned in the 'compute' format, straight out of 

the libraries. Unique to the integers, the basis vectors can be 

returned as an LLL basis. Note the similarities and differences 

in the results. The 'pivot' format is not available, since the 

integers are not a field. :: 

  

sage: A = matrix(ZZ, [[8, 0, 7, 1, 3, 4, 6], 

....: [4, 0, 3, 4, 2, 7, 7], 

....: [1, 4, 6, 1, 2, 8, 5], 

....: [0, 3, 1, 2, 3, 6, 2]]) 

  

sage: X = A.right_kernel_matrix(algorithm='default', basis='echelon'); X 

[ 1 12 3 14 -3 -10 1] 

[ 0 35 0 25 -1 -31 17] 

[ 0 0 7 12 -3 -1 -8] 

sage: A*X.transpose() == zero_matrix(ZZ, 4, 3) 

True 

  

sage: X = A.right_kernel_matrix(algorithm='padic', basis='LLL'); X 

[ -3 -1 5 7 2 -3 -2] 

[ 3 1 2 5 -5 2 -6] 

[ -4 -13 2 -7 5 7 -3] 

sage: A*X.transpose() == zero_matrix(ZZ, 4, 3) 

True 

  

sage: X = A.right_kernel_matrix(algorithm='pari', basis='computed'); X 

[ -3 -1 5 7 2 -3 -2] 

[ 3 1 2 5 -5 2 -6] 

[ -4 -13 2 -7 5 7 -3] 

sage: A*X.transpose() == zero_matrix(ZZ, 4, 3) 

True 

  

sage: X = A.right_kernel_matrix(algorithm='padic', basis='computed'); X 

[ 265 345 -178 17 -297 0 0] 

[-242 -314 163 -14 271 -1 0] 

[ -36 -47 25 -1 40 0 -1] 

sage: A*X.transpose() == zero_matrix(ZZ, 4, 3) 

True 

  

We test that the code for integer matrices is called for matrices 

defined over the integers, both dense and sparse, with equal result. :: 

  

sage: A = matrix(ZZ, [[8, 0, 7, 1, 3, 4, 6], 

....: [4, 0, 3, 4, 2, 7, 7], 

....: [1, 4, 6, 1, 2, 8, 5], 

....: [0, 3, 1, 2, 3, 6, 2]], 

....: sparse=False) 

sage: B = copy(A).sparse_matrix() 

sage: set_verbose(1) 

sage: D = A.right_kernel(); D 

verbose 1 (<module>) computing a right kernel for 4x7 matrix over Integer Ring 

verbose 1 (<module>) computing right kernel matrix over the integers for 4x7 matrix 

... 

verbose 1 (<module>) done computing right kernel matrix over the integers for 4x7 matrix 

... 

Free module of degree 7 and rank 3 over Integer Ring 

Echelon basis matrix: 

[ 1 12 3 14 -3 -10 1] 

[ 0 35 0 25 -1 -31 17] 

[ 0 0 7 12 -3 -1 -8] 

sage: S = B.right_kernel(); S 

verbose 1 (<module>) computing a right kernel for 4x7 matrix over Integer Ring 

verbose 1 (<module>) computing right kernel matrix over the integers for 4x7 matrix 

... 

verbose 1 (<module>) done computing right kernel matrix over the integers for 4x7 matrix 

... 

Free module of degree 7 and rank 3 over Integer Ring 

Echelon basis matrix: 

[ 1 12 3 14 -3 -10 1] 

[ 0 35 0 25 -1 -31 17] 

[ 0 0 7 12 -3 -1 -8] 

sage: set_verbose(0) 

sage: D == S 

True 

  

Over Principal Ideal Domains: 

  

Kernels can be computed using Smith normal form. Only the default 

algorithm is available, and the 'pivot' basis format is 

not available. :: 

  

sage: R.<y> = QQ[] 

sage: A = matrix(R, [[ 1, y, 1+y^2], 

....: [y^3, y^2, 2*y^3]]) 

sage: E = A.right_kernel_matrix(algorithm='default', basis='echelon'); E 

[-1 -y 1] 

sage: A*E.transpose() == zero_matrix(ZZ, 2, 1) 

True 

  

It can be computationally expensive to determine if an integral 

domain is a principal ideal domain. The Smith normal form routine 

can fail for non-PIDs, as in this example. :: 

  

sage: D.<x> = ZZ[] 

sage: A = matrix(D, 2, 2, [[x^2 - x, -x + 5], 

....: [x^2 - 8, -x + 2]]) 

sage: A.right_kernel_matrix() 

Traceback (most recent call last): 

... 

ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of Univariate Polynomial Ring in x over Integer Ring not principal 

  

We test that the domain code is called for domains that lack any 

extra structure. :: 

  

sage: R.<y> = QQ[] 

sage: A = matrix(R, [[ 1, y, 1+y^2], 

....: [y^3, y^2, 2*y^3]]) 

sage: set_verbose(1) 

sage: A.right_kernel(algorithm='default', basis='echelon') 

verbose ... 

verbose 1 (<module>) computing right kernel matrix over a domain for 2x3 matrix 

verbose 1 (<module>) done computing right kernel matrix over a domain for 2x3 matrix 

... 

Free module of degree 3 and rank 1 over Univariate Polynomial Ring in y over Rational Field 

Echelon basis matrix: 

[-1 -y 1] 

sage: set_verbose(0) 

  

Trivial Cases: 

  

We test two trivial cases. Any possible values for the 

keywords (``algorithm``, ``basis``) will return identical results. :: 

  

sage: A = matrix(ZZ, 0, 2) 

sage: A.right_kernel_matrix() 

[1 0] 

[0 1] 

sage: A = matrix(FiniteField(7), 2, 0) 

sage: A.right_kernel_matrix().parent() 

Full MatrixSpace of 0 by 0 dense matrices over Finite Field of size 7 

  

TESTS: 

  

The "usual" quaternions are a non-commutative ring and computations 

of kernels over these rings are not implemented. :: 

  

sage: Q.<i,j,k> = QuaternionAlgebra(-1,-1) 

sage: A = matrix(Q, 2, [i,j,-1,k]) 

sage: A.right_kernel_matrix() 

Traceback (most recent call last): 

... 

NotImplementedError: Cannot compute a matrix kernel over Quaternion Algebra (-1, -1) with base ring Rational Field 

  

We test error messages for improper choices of the 'algorithm' 

keyword. :: 

  

sage: matrix(ZZ, 2, 2).right_kernel_matrix(algorithm='junk') 

Traceback (most recent call last): 

... 

ValueError: matrix kernel algorithm 'junk' not recognized 

sage: matrix(GF(2), 2, 2).right_kernel_matrix(algorithm='padic') 

Traceback (most recent call last): 

... 

ValueError: 'padic' matrix kernel algorithm only available over the rationals and the integers, not over Finite Field of size 2 

sage: matrix(QQ, 2, 2).right_kernel_matrix(algorithm='pari') 

Traceback (most recent call last): 

... 

ValueError: 'pari' matrix kernel algorithm only available over non-trivial number fields and the integers, not over Rational Field 

sage: matrix(Integers(6), 2, 2).right_kernel_matrix(algorithm='generic') 

Traceback (most recent call last): 

... 

NotImplementedError: Echelon form not implemented over 'Ring of integers modulo 6'. 

sage: matrix(QQ, 2, 2).right_kernel_matrix(algorithm='pluq') 

Traceback (most recent call last): 

... 

ValueError: 'pluq' matrix kernel algorithm only available over integers mod 2, not over Rational Field 

  

We test error messages for improper basis format requests. :: 

  

sage: matrix(ZZ, 2, 2).right_kernel_matrix(basis='junk') 

Traceback (most recent call last): 

... 

ValueError: matrix kernel basis format 'junk' not recognized 

sage: matrix(ZZ, 2, 2).right_kernel_matrix(basis='pivot') 

Traceback (most recent call last): 

... 

ValueError: pivot basis only available over a field, not over Integer Ring 

sage: matrix(QQ, 2, 2).right_kernel_matrix(basis='LLL') 

Traceback (most recent call last): 

... 

ValueError: LLL-reduced basis only available over the integers, not over Rational Field 

  

Finally, error messages for the 'proof' keyword. :: 

  

sage: matrix(ZZ, 2, 2).right_kernel_matrix(proof='junk') 

Traceback (most recent call last): 

... 

ValueError: 'proof' must be one of True, False or None, not junk 

sage: matrix(QQ, 2, 2).right_kernel_matrix(proof=True) 

Traceback (most recent call last): 

... 

ValueError: 'proof' flag only valid for matrices over the integers 

  

AUTHOR: 

  

- Rob Beezer (2011-02-05) 

""" 

R = self.base_ring() 

  

# First: massage keywords 

# Determine algorithm to use for computation of kernel matrix 

algorithm = kwds.pop('algorithm', None) 

if algorithm is None: 

algorithm = 'default' 

elif not algorithm in ['default', 'generic', 'flint', 'pari', 'padic', 'pluq']: 

raise ValueError("matrix kernel algorithm '%s' not recognized" % algorithm ) 

elif algorithm == 'padic' and not (is_IntegerRing(R) or is_RationalField(R)): 

raise ValueError("'padic' matrix kernel algorithm only available over the rationals and the integers, not over %s" % R) 

elif algorithm == 'flint' and not (is_IntegerRing(R) or is_RationalField(R)): 

raise ValueError("'flint' matrix kernel algorithm only available over the rationals and the integers, not over %s" % R) 

elif algorithm == 'pari' and not (is_IntegerRing(R) or (is_NumberField(R) and not is_RationalField(R))): 

raise ValueError("'pari' matrix kernel algorithm only available over non-trivial number fields and the integers, not over %s" % R) 

elif algorithm == 'generic' and not R.is_field(): 

raise ValueError("'generic' matrix kernel algorithm only available over a field, not over %s" % R) 

elif algorithm == 'pluq' and not isinstance(self, sage.matrix.matrix_mod2_dense.Matrix_mod2_dense): 

raise ValueError("'pluq' matrix kernel algorithm only available over integers mod 2, not over %s" % R) 

  

# Determine the basis format of independent spanning set to return 

basis = kwds.pop('basis', None) 

if basis is None: 

basis = 'echelon' 

elif not basis in ['computed', 'echelon', 'pivot', 'LLL']: 

raise ValueError("matrix kernel basis format '%s' not recognized" % basis ) 

elif basis == 'pivot' and not R.is_field(): 

raise ValueError('pivot basis only available over a field, not over %s' % R) 

elif basis == 'LLL' and not is_IntegerRing(R): 

raise ValueError('LLL-reduced basis only available over the integers, not over %s' % R) 

  

# Determine proof keyword for integer matrices 

proof = kwds.pop('proof', None) 

if not (proof in [None, True, False]): 

raise ValueError("'proof' must be one of True, False or None, not %s" % proof) 

if not (proof is None or is_IntegerRing(R)): 

raise ValueError("'proof' flag only valid for matrices over the integers") 

  

# We could sanitize/process remaining (un-popped) keywords here and 

# send them to the echelon form routine in the 'generic' algorithm case 

# Would need to handle 'algorithm' keyword properly 

  

# Second: Trivial cases over any integral domain 

# With zero columns the domain has dimension 0, 

# so only an empty basis is possible 

# With zero rows the codomain is just the zero vector, 

# thus the kernel is the whole domain, so return an identity matrix 

# identity_matrix constructor will fail if ring does not have a one 

# For all keywords the results are identical 

if self._ncols == 0 and R.is_integral_domain(): 

return self.new_matrix(nrows=0, ncols=self._ncols) 

if self._nrows == 0 and R.is_integral_domain(): 

return self.matrix_space(self._ncols, self._ncols).identity_matrix() 

  

# Third: generic first, if requested explicitly 

# then try specialized class methods, and finally 

# delegate to ad-hoc methods in greater generality 

M = None; format = '' 

  

if algorithm == 'generic': 

format, M = self._right_kernel_matrix_over_field() 

  

if M is None: 

try: 

format, M = self._right_kernel_matrix(algorithm=algorithm, proof=proof) 

except AttributeError: 

pass 

  

if M is None and is_NumberField(R): 

format, M = self._right_kernel_matrix_over_number_field() 

  

if M is None and R.is_field(): 

format, M = self._right_kernel_matrix_over_field() 

  

if M is None and R.is_integral_domain(): 

format, M = self._right_kernel_matrix_over_domain() 

  

if M is None: 

raise NotImplementedError("Cannot compute a matrix kernel over %s" % R) 

  

# Trivial kernels give empty matrices, which sometimes mistakenly have 

# zero columns as well. (eg PARI?) This could be fixed at the source 

# with a careful study of the phenomenon. Start by commenting out 

# the following and running doctests in sage/matrix 

if M.nrows()==0 and M.ncols()!=self.ncols(): 

M = M.new_matrix(nrows=0, ncols=self.ncols()) 

  

# Convert basis to requested type and return the matrix 

# format string leads with 'echelon', 'pivot' or 'LLL' if known 

# to be of that format otherwise format string leads with 

# 'computed' if it needs work (ie raw results) 

if basis == 'computed': 

return M 

elif basis == 'echelon': 

if not format[:7] == 'echelon': 

M.echelonize() 

return M 

else: 

return M 

elif basis == 'pivot': 

# cannot get here unless over a field 

if not format[:5] == 'pivot': 

# convert non-pivot columns to identity matrix 

# this is the basis immediately obvious from echelon form 

# so C is always invertible (when working over a field) 

C = M.matrix_from_columns(self.nonpivots()) 

return C.inverse()*M 

else: 

return M 

elif basis == 'LLL': 

# cannot get here unless over integers 

if not format[:3] == 'LLL': 

return M.LLL() 

else: 

return M 

  

def right_kernel(self, *args, **kwds): 

r""" 

Returns the right kernel of this matrix, as a vector space or 

free module. This is the set of vectors ``x`` such that ``self*x = 0``. 

  

.. NOTE:: 

  

For the left kernel, use :meth:`left_kernel`. The method 

:meth:`kernel` is exactly equal to :meth:`left_kernel`. 

  

INPUT: 

  

- ``algorithm`` - default: 'default' - a keyword that selects the 

algorithm employed. Allowable values are: 

  

- 'default' - allows the algorithm to be chosen automatically 

- 'generic' - naive algorithm usable for matrices over any field 

- 'flint' - FLINT library code for matrices over the rationals 

or the integers 

- 'pari' - PARI library code for matrices over number fields 

or the integers 

- 'padic' - padic algorithm from IML library for matrices 

over the rationals and integers 

- 'pluq' - PLUQ matrix factorization for matrices mod 2 

  

- ``basis`` - default: 'echelon' - a keyword that describes the 

format of the basis used to construct the right kernel. 

Allowable values are: 

  

- 'echelon': the basis matrix is returned in echelon form 

- 'pivot' : each basis vector is computed from the reduced 

row-echelon form of ``self`` by placing a single one in a 

non-pivot column and zeros in the remaining non-pivot columns. 

Only available for matrices over fields. 

- 'LLL': an LLL-reduced basis. Only available for matrices 

over the integers. 

  

OUTPUT: 

  

A vector space or free module whose degree equals the number 

of columns in ``self`` and which contains all the vectors ``x`` 

such that ``self*x = 0``. 

  

If ``self`` has 0 columns, the kernel has dimension 0, while if 

``self`` has 0 rows the kernel is the entire ambient vector space. 

  

The result is cached. Requesting the right kernel a second time, 

but with a different basis format, will return the cached result 

with the format from the first computation. 

  

.. NOTE:: 

  

For more detailed documentation on the selection of algorithms 

used and a more flexible method for computing a basis matrix 

for a right kernel (rather than computing a vector space), see 

:meth:`right_kernel_matrix`, which powers the computations for 

this method. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, [[0, 0, 1, 2, 2, -5, 3], 

....: [-1, 5, 2, 2, 1, -7, 5], 

....: [0, 0, -2, -3, -3, 8, -5], 

....: [-1, 5, 0, -1, -2, 1, 0]]) 

sage: K = A.right_kernel(); K 

Vector space of degree 7 and dimension 4 over Rational Field 

Basis matrix: 

[ 1 0 0 0 -1 -1 -1] 

[ 0 1 0 0 5 5 5] 

[ 0 0 1 0 -1 -2 -3] 

[ 0 0 0 1 0 1 1] 

sage: A*K.basis_matrix().transpose() == zero_matrix(QQ, 4, 4) 

True 

  

The default is basis vectors that form a matrix in echelon form. 

A "pivot basis" instead has a basis matrix where the columns of 

an identity matrix are in the locations of the non-pivot columns 

of the original matrix. This alternate format is available whenever 

the base ring is a field. :: 

  

sage: A = matrix(QQ, [[0, 0, 1, 2, 2, -5, 3], 

....: [-1, 5, 2, 2, 1, -7, 5], 

....: [0, 0, -2, -3, -3, 8, -5], 

....: [-1, 5, 0, -1, -2, 1, 0]]) 

sage: A.rref() 

[ 1 -5 0 0 1 1 -1] 

[ 0 0 1 0 0 -1 1] 

[ 0 0 0 1 1 -2 1] 

[ 0 0 0 0 0 0 0] 

sage: A.nonpivots() 

(1, 4, 5, 6) 

sage: K = A.right_kernel(basis='pivot'); K 

Vector space of degree 7 and dimension 4 over Rational Field 

User basis matrix: 

[ 5 1 0 0 0 0 0] 

[-1 0 0 -1 1 0 0] 

[-1 0 1 2 0 1 0] 

[ 1 0 -1 -1 0 0 1] 

sage: A*K.basis_matrix().transpose() == zero_matrix(QQ, 4, 4) 

True 

  

Matrices may have any field as a base ring. Number fields are 

computed by PARI library code, matrices over `GF(2)` are computed 

by the M4RI library, and matrices over the rationals are computed by 

the IML library. For any of these specialized cases, general-purpose 

code can be called instead with the keyword setting 

``algorithm='generic'``. 

  

Over an arbitrary field, with two basis formats. Same vector space, 

different bases. :: 

  

sage: F.<a> = FiniteField(5^2) 

sage: A = matrix(F, 3, 4, [[ 1, a, 1+a, a^3+a^5], 

....: [ a, a^4, a+a^4, a^4+a^8], 

....: [a^2, a^6, a^2+a^6, a^5+a^10]]) 

sage: K = A.right_kernel(); K 

Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2 

Basis matrix: 

[ 1 0 3*a + 4 2*a + 2] 

[ 0 1 2*a 3*a + 3] 

sage: A*K.basis_matrix().transpose() == zero_matrix(F, 3, 2) 

True 

  

In the following test, we have to force usage of 

:class:`~sage.matrix.matrix_generic_dense.Matrix_generic_dense`, 

since the option ``basis = 'pivot'`` would simply yield the same 

result as the previous test, if the optional meataxe package is 

installed. :: 

  

sage: from sage.matrix.matrix_generic_dense import Matrix_generic_dense 

sage: B = Matrix_generic_dense(A.parent(), A.list(), False, False) 

sage: P = B.right_kernel(basis = 'pivot'); P 

Vector space of degree 4 and dimension 2 over Finite Field in a of size 5^2 

User basis matrix: 

[ 4 4 1 0] 

[ a + 2 3*a + 3 0 1] 

  

If the optional meataxe package is installed, we again have to make sure 

to work with a copy of B that has the same type as ``P.basis_matrix()``:: 

  

sage: B.parent()(B.list())*P.basis_matrix().transpose() == zero_matrix(F, 3, 2) 

True 

sage: K == P 

True 

  

Over number fields, PARI is used by default, but general-purpose code 

can be requested. Same vector space, same bases, different code.:: 

  

sage: Q = QuadraticField(-7) 

sage: a = Q.gen(0) 

sage: A = matrix(Q, [[ 2, 5-a, 15-a, 16+4*a], 

....: [2+a, a, -7 + 5*a, -3+3*a]]) 

sage: K = A.right_kernel(algorithm='default'); K 

Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7 

Basis matrix: 

[ 1 0 7/88*a + 3/88 -3/176*a - 39/176] 

[ 0 1 -1/88*a - 13/88 13/176*a - 7/176] 

sage: A*K.basis_matrix().transpose() == zero_matrix(Q, 2, 2) 

True 

sage: B = copy(A) 

sage: G = A.right_kernel(algorithm='generic'); G 

Vector space of degree 4 and dimension 2 over Number Field in a with defining polynomial x^2 + 7 

Basis matrix: 

[ 1 0 7/88*a + 3/88 -3/176*a - 39/176] 

[ 0 1 -1/88*a - 13/88 13/176*a - 7/176] 

sage: B*G.basis_matrix().transpose() == zero_matrix(Q, 2, 2) 

True 

sage: K == G 

True 

  

For matrices over the integers, several options are possible. 

The basis can be an LLL-reduced basis or an echelon basis. 

The pivot basis isnot available. A heuristic will decide whether 

to use a p-adic algorithm from the IML library or an algorithm 

from the PARI library. Note how specifying the algorithm can 

mildly influence the LLL basis. :: 

  

sage: A = matrix(ZZ, [[0, -1, -1, 2, 9, 4, -4], 

....: [-1, 1, 0, -2, -7, -1, 6], 

....: [2, 0, 1, 0, 1, -5, -2], 

....: [-1, -1, -1, 3, 10, 10, -9], 

....: [-1, 2, 0, -3, -7, 1, 6]]) 

sage: A.right_kernel(basis='echelon') 

Free module of degree 7 and rank 2 over Integer Ring 

Echelon basis matrix: 

[ 1 5 -8 3 -1 -1 -1] 

[ 0 11 -19 5 -2 -3 -3] 

sage: B = copy(A) 

sage: B.right_kernel(basis='LLL') 

Free module of degree 7 and rank 2 over Integer Ring 

User basis matrix: 

[ 2 -1 3 1 0 1 1] 

[-5 -3 2 -5 1 -1 -1] 

sage: C = copy(A) 

sage: C.right_kernel(basis='pivot') 

Traceback (most recent call last): 

... 

ValueError: pivot basis only available over a field, not over Integer Ring 

sage: D = copy(A) 

sage: D.right_kernel(algorithm='pari') 

Free module of degree 7 and rank 2 over Integer Ring 

Echelon basis matrix: 

[ 1 5 -8 3 -1 -1 -1] 

[ 0 11 -19 5 -2 -3 -3] 

sage: E = copy(A) 

sage: E.right_kernel(algorithm='padic', basis='LLL') 

Free module of degree 7 and rank 2 over Integer Ring 

User basis matrix: 

[-2 1 -3 -1 0 -1 -1] 

[ 5 3 -2 5 -1 1 1] 

  

Besides the integers, rings may be as general as principal ideal 

domains. Results are then free modules. :: 

  

sage: R.<y> = QQ[] 

sage: A = matrix(R, [[ 1, y, 1+y^2], 

....: [y^3, y^2, 2*y^3]]) 

sage: K = A.right_kernel(algorithm='default', basis='echelon'); K 

Free module of degree 3 and rank 1 over Univariate Polynomial Ring in y over Rational Field 

Echelon basis matrix: 

[-1 -y 1] 

sage: A*K.basis_matrix().transpose() == zero_matrix(ZZ, 2, 1) 

True 

  

It is possible to compute a kernel for a matrix over an integral 

domain which is not a PID, but usually this will fail. :: 

  

sage: D.<x> = ZZ[] 

sage: A = matrix(D, 2, 2, [[x^2 - x, -x + 5], 

....: [x^2 - 8, -x + 2]]) 

sage: A.right_kernel() 

Traceback (most recent call last): 

... 

ArithmeticError: Ideal Ideal (x^2 - x, x^2 - 8) of Univariate Polynomial Ring in x over Integer Ring not principal 

  

Matrices over non-commutative rings are not a good idea either. 

These are the "usual" quaternions. :: 

  

sage: Q.<i,j,k> = QuaternionAlgebra(-1,-1) 

sage: A = matrix(Q, 2, [i,j,-1,k]) 

sage: A.right_kernel() 

Traceback (most recent call last): 

... 

NotImplementedError: Cannot compute a matrix kernel over Quaternion Algebra (-1, -1) with base ring Rational Field 

  

Sparse matrices, over the rationals and the integers, 

use the same routines as the dense versions. :: 

  

sage: A = matrix(ZZ, [[0, -1, 1, 1, 2], 

....: [1, -2, 0, 1, 3], 

....: [-1, 2, 0, -1, -3]], 

....: sparse=True) 

sage: A.right_kernel() 

Free module of degree 5 and rank 3 over Integer Ring 

Echelon basis matrix: 

[ 1 0 0 2 -1] 

[ 0 1 0 -1 1] 

[ 0 0 1 -3 1] 

sage: B = A.change_ring(QQ) 

sage: B.is_sparse() 

True 

sage: B.right_kernel() 

Vector space of degree 5 and dimension 3 over Rational Field 

Basis matrix: 

[ 1 0 0 2 -1] 

[ 0 1 0 -1 1] 

[ 0 0 1 -3 1] 

  

With no columns, the kernel can only have dimension zero. 

With no rows, every possible vector is in the kernel. :: 

  

sage: A = matrix(QQ, 2, 0) 

sage: A.right_kernel() 

Vector space of degree 0 and dimension 0 over Rational Field 

Basis matrix: 

[] 

sage: A = matrix(QQ, 0, 2) 

sage: A.right_kernel() 

Vector space of degree 2 and dimension 2 over Rational Field 

Basis matrix: 

[1 0] 

[0 1] 

  

Every vector is in the kernel of a zero matrix, the 

dimension is the number of columns. :: 

  

sage: A = zero_matrix(QQ, 10, 20) 

sage: A.right_kernel() 

Vector space of degree 20 and dimension 20 over Rational Field 

Basis matrix: 

20 x 20 dense matrix over Rational Field 

  

Results are cached as the right kernel of the matrix. 

Subsequent requests for the right kernel will return 

the cached result, without regard for new values of the 

algorithm or format keyword. Work with a copy if you 

need a new right kernel, or perhaps investigate the 

:meth:`right_kernel_matrix` method, which does not 

cache its results and is more flexible. :: 

  

sage: A = matrix(QQ, 3, 3, range(9)) 

sage: K1 = A.right_kernel(basis='echelon') 

sage: K1 

Vector space of degree 3 and dimension 1 over Rational Field 

Basis matrix: 

[ 1 -2 1] 

sage: K2 = A.right_kernel(basis='pivot') 

sage: K2 

Vector space of degree 3 and dimension 1 over Rational Field 

Basis matrix: 

[ 1 -2 1] 

sage: K1 is K2 

True 

sage: B = copy(A) 

sage: K3 = B.kernel(basis='pivot') 

sage: K3 

Vector space of degree 3 and dimension 1 over Rational Field 

User basis matrix: 

[ 1 -2 1] 

sage: K3 is K1 

False 

sage: K3 == K1 

True 

""" 

K = self.fetch('right_kernel') 

if not K is None: 

verbose("retrieving cached right kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1) 

return K 

  

R = self.base_ring() 

tm = verbose("computing a right kernel for %sx%s matrix over %s" % (self.nrows(), self.ncols(), R),level=1) 

  

# Sanitize basis format 

# 'computed' is OK in right_kernel_matrix(), but not here 

# 'echelon' is default here (and elsewhere) 

# everything else gets checked in right_kernel_matrix() 

basis = kwds.pop('basis', None) 

if basis == 'computed': 

raise ValueError("kernel basis format 'computed' not supported for kernels (just right kernel matrices)") 

if basis is None: 

basis = 'echelon' 

kwds['basis'] = basis 

  

# Go get the kernel matrix, this is where it all happens 

M = self.right_kernel_matrix(*args, **kwds) 

  

ambient = R**self.ncols() 

if basis == 'echelon': 

K = ambient.submodule(M.rows(), already_echelonized=True, check=False) 

else: 

K = ambient.submodule_with_basis(M.rows(), already_echelonized=False, check=False) 

  

verbose("done computing a right kernel for %sx%s matrix over %s" % (self.nrows(), self.ncols(), R),level=1, t=tm) 

self.cache('right_kernel', K) 

return K 

  

def left_kernel(self, *args, **kwds): 

r""" 

Returns the left kernel of this matrix, as a vector space or free module. 

This is the set of vectors ``x`` such that ``x*self = 0``. 

  

.. NOTE:: 

  

For the right kernel, use :meth:`right_kernel`. The method 

:meth:`kernel` is exactly equal to :meth:`left_kernel`. 

  

INPUT: 

  

- ``algorithm`` - default: 'default' - a keyword that selects the 

algorithm employed. Allowable values are: 

  

- 'default' - allows the algorithm to be chosen automatically 

- 'generic' - naive algorithm usable for matrices over any field 

- 'flint' - FLINT library code for matrices over the rationals 

or the integers 

- 'pari' - PARI library code for matrices over number fields 

or the integers 

- 'padic' - padic algorithm from IML library for matrices 

over the rationals and integers 

- 'pluq' - PLUQ matrix factorization for matrices mod 2 

  

- ``basis`` - default: 'echelon' - a keyword that describes 

the format of the basis used to construct the left kernel. 

Allowable values are: 

  

- 'echelon': the basis matrix is returned in echelon form 

- 'pivot' : each basis vector is computed from the reduced 

row-echelon form of ``self`` by placing a single one in a 

non-pivot column and zeros in the remaining non-pivot columns. 

Only available for matrices over fields. 

- 'LLL': an LLL-reduced basis. Only available for matrices 

over the integers. 

  

OUTPUT: 

  

A vector space or free module whose degree equals the number 

of rows in ``self`` and which contains all the vectors ``x`` such 

that ``x*self = 0``. 

  

If ``self`` has 0 rows, the kernel has dimension 0, while if ``self`` 

has 0 columns the kernel is the entire ambient vector space. 

  

The result is cached. Requesting the left kernel a second time, 

but with a different basis format, will return the cached result 

with the format from the first computation. 

  

.. NOTE:: 

  

For much more detailed documentation of the various options see 

:meth:`right_kernel`, since this method just computes 

the right kernel of the transpose of ``self``. 

  

EXAMPLES: 

  

Over the rationals with a basis matrix in echelon form. :: 

  

sage: A = matrix(QQ, [[1, 2, 4, -7, 4], 

....: [1, 1, 0, 2, -1], 

....: [1, 0, 3, -3, 1], 

....: [0, -1, -1, 3, -2], 

....: [0, 0, -1, 2, -1]]) 

sage: A.left_kernel() 

Vector space of degree 5 and dimension 2 over Rational Field 

Basis matrix: 

[ 1 0 -1 2 -1] 

[ 0 1 -1 1 -4] 

  

Over a finite field, with a basis matrix in "pivot" format. :: 

  

sage: A = matrix(FiniteField(7), [[5, 0, 5, 2, 4], 

....: [1, 3, 2, 3, 6], 

....: [1, 1, 6, 5, 3], 

....: [2, 5, 6, 0, 0]]) 

sage: A.kernel(basis='pivot') 

Vector space of degree 4 and dimension 2 over Finite Field of size 7 

User basis matrix: 

[5 2 1 0] 

[6 3 0 1] 

  

The left kernel of a zero matrix is the entire ambient vector 

space whose degree equals the number of rows of ``self`` 

(i.e. everything). :: 

  

sage: A = MatrixSpace(QQ, 3, 4)(0) 

sage: A.kernel() 

Vector space of degree 3 and dimension 3 over Rational Field 

Basis matrix: 

[1 0 0] 

[0 1 0] 

[0 0 1] 

  

We test matrices with no rows or columns. :: 

  

sage: A = matrix(QQ, 2, 0) 

sage: A.left_kernel() 

Vector space of degree 2 and dimension 2 over Rational Field 

Basis matrix: 

[1 0] 

[0 1] 

sage: A = matrix(QQ, 0, 2) 

sage: A.left_kernel() 

Vector space of degree 0 and dimension 0 over Rational Field 

Basis matrix: 

[] 

  

The results are cached. Note that requesting a new format 

for the basis is ignored and the cached copy is returned. 

Work with a copy if you need a new left kernel, or perhaps 

investigate the :meth:`right_kernel_matrix` method on the 

transpose, which does not cache its results and is more 

flexible. :: 

  

sage: A = matrix(QQ, [[1,1],[2,2]]) 

sage: K1 = A.left_kernel() 

sage: K1 

Vector space of degree 2 and dimension 1 over Rational Field 

Basis matrix: 

[ 1 -1/2] 

sage: K2 = A.left_kernel() 

sage: K1 is K2 

True 

sage: K3 = A.left_kernel(basis='pivot') 

sage: K3 

Vector space of degree 2 and dimension 1 over Rational Field 

Basis matrix: 

[ 1 -1/2] 

sage: B = copy(A) 

sage: K3 = B.left_kernel(basis='pivot') 

sage: K3 

Vector space of degree 2 and dimension 1 over Rational Field 

User basis matrix: 

[-2 1] 

sage: K3 is K1 

False 

sage: K3 == K1 

True 

""" 

K = self.fetch('left_kernel') 

if not K is None: 

verbose("retrieving cached left kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1) 

return K 

  

tm = verbose("computing left kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1) 

K = self.transpose().right_kernel(*args, **kwds) 

self.cache('left_kernel', K) 

verbose("done computing left kernel for %sx%s matrix" % (self.nrows(), self.ncols()),level=1,t=tm) 

return K 

  

# .kernel() is a an alias for .left_kernel() 

kernel = left_kernel 

  

def kernel_on(self, V, poly=None, check=True): 

""" 

Return the kernel of self restricted to the invariant subspace V. 

The result is a vector subspace of V, which is also a subspace 

of the ambient space. 

  

INPUT: 

  

- ``V`` - vector subspace 

  

- ``check`` - (optional) default: True; whether to check that 

V is invariant under the action of self. 

  

- ``poly`` - (optional) default: None; if not None, compute instead 

the kernel of poly(self) on V. 

  

OUTPUT: 

  

- a subspace 

  

.. warning:: 

  

This function does *not* check that V is in fact 

invariant under self if check is False. With check False this 

function is much faster. 

  

EXAMPLES:: 

  

sage: t = matrix(QQ, 4, [39, -10, 0, -12, 0, 2, 0, -1, 0, 1, -2, 0, 0, 2, 0, -2]); t 

[ 39 -10 0 -12] 

[ 0 2 0 -1] 

[ 0 1 -2 0] 

[ 0 2 0 -2] 

sage: t.fcp() 

(x - 39) * (x + 2) * (x^2 - 2) 

sage: s = (t-39)*(t^2-2) 

sage: V = s.kernel(); V 

Vector space of degree 4 and dimension 3 over Rational Field 

Basis matrix: 

[1 0 0 0] 

[0 1 0 0] 

[0 0 0 1] 

sage: s.restrict(V) 

[0 0 0] 

[0 0 0] 

[0 0 0] 

sage: s.kernel_on(V) 

Vector space of degree 4 and dimension 3 over Rational Field 

Basis matrix: 

[1 0 0 0] 

[0 1 0 0] 

[0 0 0 1] 

sage: k = t-39 

sage: k.restrict(V) 

[ 0 -10 -12] 

[ 0 -37 -1] 

[ 0 2 -41] 

sage: ker = k.kernel_on(V); ker 

Vector space of degree 4 and dimension 1 over Rational Field 

Basis matrix: 

[ 1 -2/7 0 -2/7] 

sage: ker.0 * k 

(0, 0, 0, 0) 

  

Test that :trac:`9425` is fixed. 

  

:: 

  

sage: V = span([[1/7,0,0] ,[0,1,0]], ZZ); V 

Free module of degree 3 and rank 2 over Integer Ring 

Echelon basis matrix: 

[1/7 0 0] 

[ 0 1 0] 

sage: T = matrix(ZZ,3,[1,0,0,0,0,0,0,0,0]); T 

[1 0 0] 

[0 0 0] 

[0 0 0] 

sage: W = T.kernel_on(V); W.basis() 

[ 

(0, 1, 0) 

] 

sage: W.is_submodule(V) 

True 

""" 

A = self.restrict(V, check=check) 

if not poly is None: 

A = poly(A) 

W = A.kernel() 

if V.is_ambient(): 

return W 

else: 

A = V.basis_matrix() 

B = W.basis_matrix() 

C = B*A 

return C.row_module(base_ring=V.base_ring()) 

  

def integer_kernel(self, ring=ZZ): 

""" 

Return the kernel of this matrix over the given ring (which should be 

either the base ring, or a PID whose fraction field is the base ring). 

  

Assume that the base field of this matrix has a numerator and 

denominator functions for its elements, e.g., it is the rational 

numbers or a fraction field. This function computes a basis over 

the integers for the kernel of self. 

  

If the matrix is not coercible into QQ, then the PID itself should be 

given as a second argument, as in the third example below. 

  

EXAMPLES:: 

  

sage: A = MatrixSpace(QQ, 4)(range(16)) 

sage: A.integer_kernel() 

Free module of degree 4 and rank 2 over Integer Ring 

Echelon basis matrix: 

[ 1 0 -3 2] 

[ 0 1 -2 1] 

  

The integer kernel even makes sense for matrices with fractional 

entries:: 

  

sage: A = MatrixSpace(QQ, 2)([1/2, 0, 0, 0]) 

sage: A.integer_kernel() 

Free module of degree 2 and rank 1 over Integer Ring 

Echelon basis matrix: 

[0 1] 

  

An example over a bigger ring:: 

  

sage: L.<w> = NumberField(x^2 - x + 2) 

sage: OL = L.ring_of_integers() 

sage: A = matrix(L, 2, [1, w/2]) 

sage: A.integer_kernel(OL) 

Free module of degree 2 and rank 1 over Maximal Order in Number Field in w with defining polynomial x^2 - x + 2 

Echelon basis matrix: 

[ -1 -w + 1] 

  

""" 

try: 

A, _ = self._clear_denom() 

return A.kernel() 

except AttributeError: 

from sage.matrix.matrix_space import MatrixSpace 

d = self.denominator() 

A = self * d 

M = MatrixSpace(ring, self.nrows(), self.ncols())(A) 

return M.kernel() 

  

def image(self): 

""" 

Return the image of the homomorphism on rows defined by this 

matrix. 

  

EXAMPLES:: 

  

sage: MS1 = MatrixSpace(ZZ,4) 

sage: MS2 = MatrixSpace(QQ,6) 

sage: A = MS1.matrix([3,4,5,6,7,3,8,10,14,5,6,7,2,2,10,9]) 

sage: B = MS2.random_element() 

  

:: 

  

sage: image(A) 

Free module of degree 4 and rank 4 over Integer Ring 

Echelon basis matrix: 

[ 1 0 0 426] 

[ 0 1 0 518] 

[ 0 0 1 293] 

[ 0 0 0 687] 

  

:: 

  

sage: image(B) == B.row_module() 

True 

""" 

return self.row_module() 

  

def _row_ambient_module(self, base_ring=None): 

if base_ring is None: 

base_ring = self.base_ring() 

x = self.fetch('row_ambient_module_%s'%base_ring) 

if not x is None: 

return x 

x = sage.modules.free_module.FreeModule(base_ring, self.ncols(), sparse=self.is_sparse()) 

self.cache('row_ambient_module',x) 

return x 

  

def row_module(self, base_ring=None): 

""" 

Return the free module over the base ring spanned by the rows of 

self. 

  

EXAMPLES:: 

  

sage: A = MatrixSpace(IntegerRing(), 2)([1,2,3,4]) 

sage: A.row_module() 

Free module of degree 2 and rank 2 over Integer Ring 

Echelon basis matrix: 

[1 0] 

[0 2] 

""" 

M = self._row_ambient_module(base_ring = base_ring) 

if (base_ring is None or base_ring == self.base_ring()) and self.fetch('in_echelon_form'): 

if self.rank() != self.nrows(): 

rows = self.matrix_from_rows(range(self.rank())).rows() 

else: 

rows = self.rows() 

return M.span(rows, already_echelonized=True) 

else: 

return M.span(self.rows(), already_echelonized=False) 

  

def row_space(self, base_ring=None): 

""" 

Return the row space of this matrix. (Synonym for 

self.row_module().) 

  

EXAMPLES:: 

  

sage: t = matrix(QQ, 3, 3, range(9)); t 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: t.row_space() 

Vector space of degree 3 and dimension 2 over Rational Field 

Basis matrix: 

[ 1 0 -1] 

[ 0 1 2] 

  

:: 

  

sage: m = Matrix(Integers(5),2,2,[2,2,2,2]); 

sage: m.row_space() 

Vector space of degree 2 and dimension 1 over Ring of integers modulo 5 

Basis matrix: 

[1 1] 

""" 

return self.row_module(base_ring=base_ring) 

  

def _column_ambient_module(self): 

x = self.fetch('column_ambient_module') 

if not x is None: 

return x 

x = sage.modules.free_module.FreeModule(self.base_ring(), self.nrows(), 

sparse=self.is_sparse()) 

self.cache('column_ambient_module',x) 

return x 

  

def column_module(self): 

""" 

Return the free module over the base ring spanned by the columns of 

this matrix. 

  

EXAMPLES:: 

  

sage: t = matrix(QQ, 3, 3, range(9)); t 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: t.column_module() 

Vector space of degree 3 and dimension 2 over Rational Field 

Basis matrix: 

[ 1 0 -1] 

[ 0 1 2] 

""" 

return self.transpose().row_module() 

  

def column_space(self): 

""" 

Return the vector space over the base ring spanned by the columns 

of this matrix. 

  

EXAMPLES:: 

  

sage: M = MatrixSpace(QQ,3,3) 

sage: A = M([1,9,-7,4/5,4,3,6,4,3]) 

sage: A.column_space() 

Vector space of degree 3 and dimension 3 over Rational Field 

Basis matrix: 

[1 0 0] 

[0 1 0] 

[0 0 1] 

sage: W = MatrixSpace(CC,2,2) 

sage: B = W([1, 2+3*I,4+5*I,9]); B 

[ 1.00000000000000 2.00000000000000 + 3.00000000000000*I] 

[4.00000000000000 + 5.00000000000000*I 9.00000000000000] 

sage: B.column_space() 

Vector space of degree 2 and dimension 2 over Complex Field with 53 bits of precision 

Basis matrix: 

[ 1.00000000000000 0.000000000000000] 

[0.000000000000000 1.00000000000000] 

""" 

return self.column_module() 

  

def decomposition(self, algorithm='spin', 

is_diagonalizable=False, dual=False): 

""" 

Returns the decomposition of the free module on which this matrix A 

acts from the right (i.e., the action is x goes to x A), along with 

whether this matrix acts irreducibly on each factor. The factors 

are guaranteed to be sorted in the same way as the corresponding 

factors of the characteristic polynomial. 

  

Let A be the matrix acting from the on the vector space V of column 

vectors. Assume that A is square. This function computes maximal 

subspaces W_1, ..., W_n corresponding to Galois conjugacy classes 

of eigenvalues of A. More precisely, let `f(X)` be the characteristic 

polynomial of A. This function computes the subspace 

`W_i = ker(g_(A)^n)`, where `g_i(X)` is an irreducible 

factor of `f(X)` and `g_i(X)` exactly divides `f(X)`. If the optional 

parameter is_diagonalizable is True, then we let `W_i = ker(g(A))`, 

since then we know that `ker(g(A)) = ker(g(A)^n)`. 

  

INPUT: 

  

  

- ``self`` - a matrix 

  

- ``algorithm`` - 'spin' (default): algorithm involves 

iterating the action of self on a vector. 'kernel': naively just 

compute `ker(f_i(A))` for each factor `f_i`. 

  

- ``dual`` - bool (default: False): If True, also 

returns the corresponding decomposition of V under the action of 

the transpose of A. The factors are guaranteed to correspond. 

  

- ``is_diagonalizable`` - if the matrix is known to 

be diagonalizable, set this to True, which might speed up the 

algorithm in some cases. 

  

.. NOTE:: 

  

If the base ring is not a field, the kernel algorithm is 

used. 

  

  

OUTPUT: 

  

  

- ``Sequence`` - list of pairs (V,t), where V is a vector 

spaces and t is a bool, and t is True exactly when the 

charpoly of self on V is irreducible. 

  

  

- (optional) list - list of pairs (W,t), where W is a vector 

space and t is a bool, and t is True exactly when the 

charpoly of the transpose of self on W is irreducible. 

  

EXAMPLES:: 

  

sage: A = matrix(ZZ, 4, [3,4,5,6,7,3,8,10,14,5,6,7,2,2,10,9]) 

sage: B = matrix(QQ, 6, 6, range(36)) 

sage: B*11 

[ 0 11 22 33 44 55] 

[ 66 77 88 99 110 121] 

[132 143 154 165 176 187] 

[198 209 220 231 242 253] 

[264 275 286 297 308 319] 

[330 341 352 363 374 385] 

sage: A.decomposition() 

[ 

(Ambient free module of rank 4 over the principal ideal domain Integer Ring, True) 

] 

sage: B.decomposition() 

[ 

(Vector space of degree 6 and dimension 2 over Rational Field 

Basis matrix: 

[ 1 0 -1 -2 -3 -4] 

[ 0 1 2 3 4 5], True), 

(Vector space of degree 6 and dimension 4 over Rational Field 

Basis matrix: 

[ 1 0 0 0 -5 4] 

[ 0 1 0 0 -4 3] 

[ 0 0 1 0 -3 2] 

[ 0 0 0 1 -2 1], False) 

] 

""" 

if algorithm == 'kernel' or not self.base_ring().is_field(): 

return self._decomposition_using_kernels(is_diagonalizable = is_diagonalizable, dual=dual) 

elif algorithm == 'spin': 

X = self._decomposition_spin_generic(is_diagonalizable = is_diagonalizable) 

if dual: 

Y = self.transpose()._decomposition_spin_generic(is_diagonalizable = is_diagonalizable) 

return X, Y 

return X 

else: 

raise ValueError("no algorithm '%s'"%algorithm) 

  

def _decomposition_spin_generic(self, is_diagonalizable=False): 

r""" 

Compute the decomposition of this matrix using the spin algorithm. 

  

INPUT: 

  

- ``self`` - a matrix with field entries 

  

OUTPUT: a list of reduced row echelon form basis 

  

AUTHORS: 

  

- William Stein 

""" 

if not self.is_square(): 

raise ValueError("self must be a square matrix") 

  

if not self.base_ring().is_field(): 

raise TypeError("self must be over a field.") 

  

if self.nrows() == 0: 

return decomp_seq([]) 

  

f = self.charpoly('x') 

E = decomp_seq([]) 

  

t = verbose('factoring the characteristic polynomial', level=2, caller_name='generic spin decomp') 

F = f.factor() 

verbose('done factoring', t=t, level=2, caller_name='generic spin decomp') 

  

if len(F) == 1: 

V = self.base_ring()**self.nrows() 

return decomp_seq([(V,F[0][1]==1)]) 

  

V = self.base_ring()**self.nrows() 

v = V.random_element() 

num_iterates = max([0] + [f.degree() - g.degree() for g, _ in F if g.degree() > 1]) + 1 

  

S = [ ] 

  

F.sort() 

for i in range(len(F)): 

g, m = F[i] 

  

if g.degree() == 1: 

# Just use kernel -- much easier. 

B = self.__copy__() 

for k from 0 <= k < self.nrows(): 

B[k,k] += g[0] 

if m > 1 and not is_diagonalizable: 

B = B**m 

W = B.kernel() 

E.append((W, m==1)) 

continue 

  

# General case, i.e., deg(g) > 1: 

W = None 

tries = m 

while True: 

  

# Compute the complementary factor. 

h = f // (g**m) 

v = h.list() 

  

while len(S) < tries: 

t = verbose('%s-spinning %s-th random vector'%(num_iterates, len(S)), level=2, caller_name='generic spin decomp') 

S.append(self.iterates(V.random_element(), num_iterates)) 

verbose('done spinning', level=2, t=t, caller_name='generic spin decomp') 

  

for j in range(0 if W is None else W.nrows() // g.degree(), len(S)): 

# Compute one element of the kernel of g(A)**m. 

t = verbose('compute element of kernel of g(A), for g of degree %s'%g.degree(),level=2, 

caller_name='generic spin decomp') 

w = S[j].linear_combination_of_rows(h.list()) 

t = verbose('done computing element of kernel of g(A)', t=t,level=2, caller_name='generic spin decomp') 

  

# Get the rest of the kernel. 

t = verbose('fill out rest of kernel',level=2, caller_name='generic spin decomp') 

if W is None: 

W = self.iterates(w, g.degree()) 

else: 

W = W.stack(self.iterates(w, g.degree())) 

t = verbose('finished filling out more of kernel',level=2, t=t, caller_name='generic spin decomp') 

  

if W.rank() == m * g.degree(): 

t = verbose('now computing row space', level=2, caller_name='generic spin decomp') 

W.echelonize() 

E.append((W.row_space(), m==1)) 

verbose('computed row space', level=2,t=t, caller_name='generic spin decomp') 

break 

else: 

verbose('we have not yet generated all the kernel (rank so far=%s, target rank=%s)'%( 

W.rank(), m*g.degree()), level=2, caller_name='generic spin decomp') 

tries += 1 

if tries > 1000*m: # avoid an insanely long infinite loop 

raise RuntimeError("likely bug in decomposition") 

# end if 

#end while 

#end for 

return E 

  

def _decomposition_using_kernels(self, is_diagonalizable=False, dual=False): 

if not self.is_square(): 

raise ValueError("self must be a square matrix") 

  

if self.nrows() == 0: 

return decomp_seq([]) 

  

f = self.charpoly('x') 

E = decomp_seq([]) 

  

# Idea: For optimization, could compute powers of self 

# up to max degree of any factor. Then get g(self) 

# by taking a linear combination. 

  

if dual: 

Edual = decomp_seq([]) 

F = f.factor() 

if len(F) == 1: 

V = sage.modules.free_module.FreeModule( 

self.base_ring(), self.nrows(), sparse=self.is_sparse()) 

m = F[0][1] 

if dual: 

return decomp_seq([(V, m==1)]), decomp_seq([(V, m==1)]) 

else: 

return decomp_seq([(V, m==1)]) 

F.sort() 

for g, m in f.factor(): 

t = verbose('decomposition -- Computing g(self) for an irreducible factor g of degree %s'%g.degree(),level=2) 

if is_diagonalizable: 

B = g(self) 

else: 

B = g(self) 

t2 = verbose('decomposition -- raising g(self) to the power %s'%m,level=2) 

B = B ** m 

verbose('done powering',t2) 

t = verbose('decomposition -- done computing g(self)', level=2, t=t) 

E.append((B.kernel(), m==1)) 

t = verbose('decomposition -- time to compute kernel', level=2, t=t) 

if dual: 

Edual.append((B.transpose().kernel(), m==1)) 

verbose('decomposition -- time to compute dual kernel', level=2, t=t) 

if dual: 

return E, Edual 

return E 

  

def decomposition_of_subspace(self, M, check_restrict = True, **kwds): 

""" 

Suppose the right action of self on M leaves M invariant. Return 

the decomposition of M as a list of pairs (W, is_irred) where 

is_irred is True if the charpoly of self acting on the factor W is 

irreducible. 

  

Additional inputs besides M are passed onto the decomposition 

command. 

  

INPUT: 

  

- `M` -- A subspace of the free module ``self`` acts on. 

- ``check_restrict`` -- A boolean (default: ``True``); Call restrict 

with or without check. 

- ``kwds`` -- Keywords that will be forwarded to :meth:`~.decomposition`. 

  

EXAMPLES:: 

  

sage: t = matrix(QQ, 3, [3, 0, -2, 0, -2, 0, 0, 0, 0]); t 

[ 3 0 -2] 

[ 0 -2 0] 

[ 0 0 0] 

sage: t.fcp('X') # factored charpoly 

(X - 3) * X * (X + 2) 

sage: v = kernel(t*(t+2)); v # an invariant subspace 

Vector space of degree 3 and dimension 2 over Rational Field 

Basis matrix: 

[0 1 0] 

[0 0 1] 

sage: D = t.decomposition_of_subspace(v); D 

[ 

(Vector space of degree 3 and dimension 1 over Rational Field 

Basis matrix: 

[0 0 1], True), 

(Vector space of degree 3 and dimension 1 over Rational Field 

Basis matrix: 

[0 1 0], True) 

] 

sage: t.restrict(D[0][0]) 

[0] 

sage: t.restrict(D[1][0]) 

[-2] 

  

We do a decomposition over ZZ:: 

  

sage: a = matrix(ZZ,6,[0, 0, -2, 0, 2, 0, 2, -4, -2, 0, 2, 0, 0, 0, -2, -2, 0, 0, 2, 0, -2, -4, 2, -2, 0, 2, 0, -2, -2, 0, 0, 2, 0, -2, 0, 0]) 

sage: a.decomposition_of_subspace(ZZ^6) 

[ 

(Free module of degree 6 and rank 2 over Integer Ring 

Echelon basis matrix: 

[ 1 0 1 -1 1 -1] 

[ 0 1 0 -1 2 -1], False), 

(Free module of degree 6 and rank 4 over Integer Ring 

Echelon basis matrix: 

[ 1 0 -1 0 1 0] 

[ 0 1 0 0 0 0] 

[ 0 0 0 1 0 0] 

[ 0 0 0 0 0 1], False) 

] 

  

TESTS:: 

  

sage: t = matrix(QQ, 3, [3, 0, -2, 0, -2, 0, 0, 0, 0]); 

sage: t.decomposition_of_subspace(v, check_restrict = False) == t.decomposition_of_subspace(v) 

True 

""" 

if not sage.modules.free_module.is_FreeModule(M): 

raise TypeError("M must be a free module.") 

if not self.is_square(): 

raise ArithmeticError("self must be a square matrix") 

if M.base_ring() != self.base_ring(): 

raise ArithmeticError("base rings must be the same, but self is over %s and module is over %s"%( 

self.base_ring(), M.base_ring())) 

if M.degree() != self.ncols(): 

raise ArithmeticError("M must be a subspace of an %s-dimensional space" % self.ncols()) 

  

time = verbose(t=0) 

  

# 1. Restrict 

B = self.restrict(M, check = check_restrict) 

time0 = verbose("decompose restriction -- ", time) 

  

# 2. Decompose restriction 

D = B.decomposition(**kwds) 

  

sum_dim = sum([A.dimension() for A,_ in D]) 

assert sum_dim == M.dimension(), \ 

"bug in decomposition; " + \ 

"the sum of the dimensions (=%s) of the factors must equal the dimension (%s) of the acted on space:\nFactors found: %s\nSpace: %s"%(sum_dim, M.dimension(), D, M) 

  

# 3. Lift decomposition to subspaces of ambient vector space. 

# Each basis vector for an element of D defines a linear 

# combination of the basis of W, and these linear combinations 

# define the corresponding subspaces of the ambient space M. 

  

verbose("decomposition -- ", time0) 

C = M.basis_matrix() 

  

D = [((W.basis_matrix() * C).row_module(self.base_ring()), is_irred) for W, is_irred in D] 

D = decomp_seq(D) 

  

verbose(t=time) 

return D 

  

def restrict(self, V, check=True): 

""" 

Returns the matrix that defines the action of self on the chosen 

basis for the invariant subspace V. If V is an ambient, returns 

self (not a copy of self). 

  

INPUT: 

  

  

- ``V`` - vector subspace 

  

- ``check`` - (optional) default: True; if False may 

not check that V is invariant (hence can be faster). 

  

  

OUTPUT: a matrix 

  

.. warning:: 

  

This function returns an nxn matrix, where V has dimension 

n. It does *not* check that V is in fact invariant under 

self, unless check is True. 

  

EXAMPLES:: 

  

sage: V = VectorSpace(QQ, 3) 

sage: M = MatrixSpace(QQ, 3) 

sage: A = M([1,2,0, 3,4,0, 0,0,0]) 

sage: W = V.subspace([[1,0,0], [0,1,0]]) 

sage: A.restrict(W) 

[1 2] 

[3 4] 

sage: A.restrict(W, check=True) 

[1 2] 

[3 4] 

  

We illustrate the warning about invariance not being checked by 

default, by giving a non-invariant subspace. With the default 

check=False this function returns the 'restriction' matrix, which 

is meaningless as check=True reveals. 

  

:: 

  

sage: W2 = V.subspace([[1,0,0], [0,1,1]]) 

sage: A.restrict(W2, check=False) 

[1 2] 

[3 4] 

sage: A.restrict(W2, check=True) 

Traceback (most recent call last): 

... 

ArithmeticError: subspace is not invariant under matrix 

""" 

if not isinstance(V, sage.modules.free_module.FreeModule_generic): 

raise TypeError("V must be a free module") 

#if V.base_ring() != self.base_ring(): 

# raise ValueError("matrix and module must have the same base ring, but matrix is over %s and module is over %s"%(self.base_ring(), V.base_ring())) 

if V.degree() != self.nrows(): 

raise IndexError("degree of V (=%s) must equal number of rows of self (=%s)" % (V.degree(), self.nrows())) 

if V.rank() == 0 or V.degree() == 0: 

return self.new_matrix(nrows=0, ncols=0) 

  

if not check and V.base_ring().is_field() and not V.has_user_basis(): 

B = V.echelonized_basis_matrix() 

P = B.pivots() 

return B*self.matrix_from_columns(P) 

else: 

n = V.rank() 

try: 

# todo optimize so only involves matrix multiplies ? 

C = [V.coordinate_vector(b*self) for b in V.basis()] 

except ArithmeticError: 

raise ArithmeticError("subspace is not invariant under matrix") 

return self.new_matrix(n, n, C, sparse=False) 

  

def restrict_domain(self, V): 

""" 

Compute the matrix relative to the basis for V on the domain 

obtained by restricting self to V, but not changing the codomain of 

the matrix. This is the matrix whose rows are the images of the 

basis for V. 

  

INPUT: 

  

  

- ``V`` - vector space (subspace of ambient space on 

which self acts) 

  

  

.. SEEALSO:: 

  

:meth:`restrict` 

  

EXAMPLES:: 

  

sage: V = QQ^3 

sage: A = matrix(QQ,3,[1,2,0, 3,4,0, 0,0,0]) 

sage: W = V.subspace([[1,0,0], [1,2,3]]) 

sage: A.restrict_domain(W) 

[1 2 0] 

[3 4 0] 

sage: W2 = V.subspace_with_basis([[1,0,0], [1,2,3]]) 

sage: A.restrict_domain(W2) 

[ 1 2 0] 

[ 7 10 0] 

""" 

return V.basis_matrix() * self 

  

def restrict_codomain(self, V): 

r""" 

Suppose that self defines a linear map from some domain to a 

codomain that contains `V` and that the image of self is 

contained in `V`. This function returns a new matrix 

`A` that represents this linear map but as a map to 

`V`, in the sense that if `x` is in the domain, 

then `xA` is the linear combination of the elements of the 

basis of `V` that equals v\*self. 

  

INPUT: 

  

  

- ``V`` - vector space (space of degree 

``self.ncols()``) that contains the image of self. 

  

  

.. SEEALSO:: 

  

:meth:`restrict`, :meth:`restrict_domain` 

  

EXAMPLES:: 

  

sage: A = matrix(QQ,3,[1..9]) 

sage: V = (QQ^3).span([[1,2,3], [7,8,9]]); V 

Vector space of degree 3 and dimension 2 over Rational Field 

Basis matrix: 

[ 1 0 -1] 

[ 0 1 2] 

sage: z = vector(QQ,[1,2,5]) 

sage: B = A.restrict_codomain(V); B 

[1 2] 

[4 5] 

[7 8] 

sage: z*B 

(44, 52) 

sage: z*A 

(44, 52, 60) 

sage: 44*V.0 + 52*V.1 

(44, 52, 60) 

""" 

return V.basis_matrix().solve_left(self) 

  

def maxspin(self, v): 

""" 

Computes the largest integer n such that the list of vectors 

`S=[v, v*A, ..., v * A^n]` are linearly independent, and 

returns that list. 

  

INPUT: 

  

  

- ``self`` - Matrix 

  

- ``v`` - Vector 

  

  

OUTPUT: 

  

  

- ``list`` - list of Vectors 

  

  

ALGORITHM: The current implementation just adds vectors to a vector 

space until the dimension doesn't grow. This could be optimized by 

directly using matrices and doing an efficient Echelon form. Also, 

when the base is Q, maybe we could simultaneously keep track of 

what is going on in the reduction modulo p, which might make things 

much faster. 

  

EXAMPLES:: 

  

sage: t = matrix(QQ, 3, 3, range(9)); t 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: v = (QQ^3).0 

sage: t.maxspin(v) 

[(1, 0, 0), (0, 1, 2), (15, 18, 21)] 

sage: k = t.kernel(); k 

Vector space of degree 3 and dimension 1 over Rational Field 

Basis matrix: 

[ 1 -2 1] 

sage: t.maxspin(k.0) 

[(1, -2, 1)] 

""" 

if v == 0: 

return [] 

if not is_FreeModuleElement(v): 

raise TypeError("v must be a FreeModuleElement") 

VS = v.parent() 

V = VS.span([v]) 

w = v 

S = [v] 

while True: 

w = w*self 

W = V + VS.span([w]) 

if W.dimension() == V.dimension(): 

return S 

V = W 

S.append(w) 

  

def wiedemann(self, i, t=0): 

""" 

Application of Wiedemann's algorithm to the i-th standard basis 

vector. 

  

INPUT: 

  

  

- ``i`` - an integer 

  

- ``t`` - an integer (default: 0) if t is nonzero, use 

only the first t linear recurrence relations. 

  

  

IMPLEMENTATION: This is a toy implementation. 

  

EXAMPLES:: 

  

sage: t = matrix(QQ, 3, 3, range(9)); t 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: t.wiedemann(0) 

x^2 - 12*x - 18 

sage: t.charpoly() 

x^3 - 12*x^2 - 18*x 

""" 

i = int(i); t=int(t) 

if self.nrows() != self.ncols(): 

raise ArithmeticError("self must be a square matrix") 

n = self.nrows() 

v = sage.modules.free_module.VectorSpace(self.base_ring(), n).gen(i) 

tm = verbose('computing iterates...') 

cols = self.iterates(v, 2*n).columns() 

tm = verbose('computed iterates', tm) 

f = None 

# Compute the minimal polynomial of the linear recurrence 

# sequence corresponding to the 0-th entries of the iterates, 

# then the 1-th entries, etc. 

if t == 0: 

R = list(xrange(n)) 

else: 

R = [t] 

for i in R: 

tm = verbose('applying berlekamp-massey') 

g = berlekamp_massey.berlekamp_massey(cols[i].list()) 

verbose('berlekamp-massey done', tm) 

if f is None: 

f = g 

else: 

f = f.lcm(g) 

if f.degree() == n: 

break 

return f 

  

def _eigenspace_format(self, format): 

r""" 

Helper method to control output format for eigenspaces. 

  

INPUT: 

  

- ``format`` - ``None``, ``'all'`` or ``'galois'`` 

  

OUTPUT: 

  

Any format except ``None`` is just passed through. When the 

format is ``None`` a choice is made about the style of the output. 

If there is an algebraically closed field that will contain the 

possible eigenvalues, then 'all" of the eigenspaces are given. 

  

However if this is not the case, then only one eigenspace is output 

for each irreducible factor of the characteristic polynomial. 

  

EXAMPLES: 

  

Pass-through first. :: 

  

sage: A = matrix(QQ, 2, range(4)) 

sage: A._eigenspace_format('all') == 'all' 

True 

sage: A._eigenspace_format('galois') == 'galois' 

True 

  

The algebraic closure of the rationals (the field ``QQbar`` of 

algebraic numbers) is implemented, as are algebraic closures 

of finite fields:: 

  

sage: A = matrix(QQ, 2, range(4)) 

sage: A._eigenspace_format(None) == 'all' 

True 

sage: B = matrix(GF(13), 2, range(4)) 

sage: B._eigenspace_format(None) 

'all' 

  

Subrings are promoted to fraction fields and then checked for the 

existence of algebraic closures. :: 

  

sage: A = matrix(ZZ, 2, range(4)) 

sage: A._eigenspace_format(None) == 'all' 

True 

""" 

if not format in [None, 'all', 'galois']: 

msg = "format keyword must be None, 'all' or 'galois', not {0}" 

raise ValueError(msg.format(format)) 

  

# In the absence of a format keyword, we default to 'all' for 

# subrings of fields of which an algebraic closure is implemented. 

if format is None: 

try: 

F = self.base_ring().fraction_field().algebraic_closure() 

return 'all' 

except (NotImplementedError, AttributeError): 

return 'galois' 

else: 

return format 

  

def eigenspaces_left(self, format='all', var='a', algebraic_multiplicity=False): 

r""" 

Compute the left eigenspaces of a matrix. 

  

Note that ``eigenspaces_left()`` and ``left_eigenspaces()`` 

are identical methods. Here "left" refers to the eigenvectors 

being placed to the left of the matrix. 

  

INPUT: 

  

- ``self`` - a square matrix over an exact field. For inexact 

matrices consult the numerical or symbolic matrix classes. 

  

- ``format`` - default: ``None`` 

  

- ``'all'`` - attempts to create every eigenspace. This will 

always be possible for matrices with rational entries. 

- ``'galois'`` - for each irreducible factor of the characteristic 

polynomial, a single eigenspace will be output for a 

single root/eigenvalue for the irreducible factor. 

- ``None`` - Uses the 'all' format if the base ring is contained 

in an algebraically closed field which is implemented. 

Otherwise, uses the 'galois' format. 

  

- ``var`` - default: 'a' - variable name used to 

represent elements of the root field of each 

irreducible factor of the characteristic polynomial. 

If var='a', then the root fields will be in terms of 

a0, a1, a2, ...., where the numbering runs across all 

the irreducible factors of the characteristic polynomial, 

even for linear factors. 

  

- ``algebraic_multiplicity`` - default: False - whether or 

not to include the algebraic multiplicity of each eigenvalue 

in the output. See the discussion below. 

  

OUTPUT: 

  

If algebraic_multiplicity=False, return a list of pairs (e, V) 

where e is an eigenvalue of the matrix, and V is the corresponding 

left eigenspace. For Galois conjugates of eigenvalues, there 

may be just one representative eigenspace, depending on the 

``format`` keyword. 

  

If algebraic_multiplicity=True, return a list of triples (e, V, n) 

where e and V are as above and n is the algebraic multiplicity of 

the eigenvalue. 

  

.. warning:: 

  

Uses a somewhat naive algorithm (simply factors the 

characteristic polynomial and computes kernels directly 

over the extension field). 

  

EXAMPLES: 

  

We compute the left eigenspaces of a `3\times 3` 

rational matrix. First, we request `all` of the eigenvalues, 

so the results are in the field of algebraic numbers, `QQbar`. 

Then we request just one eigenspace per irreducible factor of 

the characteristic polynomial with the `galois` keyword. :: 

  

sage: A = matrix(QQ,3,3,range(9)); A 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: es = A.eigenspaces_left(format='all'); es 

[ 

(0, Vector space of degree 3 and dimension 1 over Rational Field 

User basis matrix: 

[ 1 -2 1]), 

(-1.348469228349535?, Vector space of degree 3 and dimension 1 over Algebraic Field 

User basis matrix: 

[ 1 0.3101020514433644? -0.3797958971132713?]), 

(13.34846922834954?, Vector space of degree 3 and dimension 1 over Algebraic Field 

User basis matrix: 

[ 1 1.289897948556636? 1.579795897113272?]) 

] 

  

sage: es = A.eigenspaces_left(format='galois'); es 

[ 

(0, Vector space of degree 3 and dimension 1 over Rational Field 

User basis matrix: 

[ 1 -2 1]), 

(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 

User basis matrix: 

[ 1 1/15*a1 + 2/5 2/15*a1 - 1/5]) 

] 

sage: es = A.eigenspaces_left(format='galois', algebraic_multiplicity=True); es 

[ 

(0, Vector space of degree 3 and dimension 1 over Rational Field 

User basis matrix: 

[ 1 -2 1], 1), 

(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 

User basis matrix: 

[ 1 1/15*a1 + 2/5 2/15*a1 - 1/5], 1) 

] 

sage: e, v, n = es[0]; v = v.basis()[0] 

sage: delta = e*v - v*A 

sage: abs(abs(delta)) < 1e-10 

True 

  

The same computation, but with implicit base change to a field. :: 

  

sage: A = matrix(ZZ,3,3,range(9)); A 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: A.eigenspaces_left(format='galois') 

[ 

(0, Vector space of degree 3 and dimension 1 over Rational Field 

User basis matrix: 

[ 1 -2 1]), 

(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 

User basis matrix: 

[ 1 1/15*a1 + 2/5 2/15*a1 - 1/5]) 

] 

  

We compute the left eigenspaces of the matrix of the Hecke operator 

`T_2` on level 43 modular symbols, both with all eigenvalues (the default) 

and with one subspace per factor. :: 

  

sage: A = ModularSymbols(43).T(2).matrix(); A 

[ 3 0 0 0 0 0 -1] 

[ 0 -2 1 0 0 0 0] 

[ 0 -1 1 1 0 -1 0] 

[ 0 -1 0 -1 2 -1 1] 

[ 0 -1 0 1 1 -1 1] 

[ 0 0 -2 0 2 -2 1] 

[ 0 0 -1 0 1 0 -1] 

sage: A.base_ring() 

Rational Field 

sage: f = A.charpoly(); f 

x^7 + x^6 - 12*x^5 - 16*x^4 + 36*x^3 + 52*x^2 - 32*x - 48 

sage: factor(f) 

(x - 3) * (x + 2)^2 * (x^2 - 2)^2 

sage: A.eigenspaces_left(algebraic_multiplicity=True) 

[ 

(3, Vector space of degree 7 and dimension 1 over Rational Field 

User basis matrix: 

[ 1 0 1/7 0 -1/7 0 -2/7], 1), 

(-2, Vector space of degree 7 and dimension 2 over Rational Field 

User basis matrix: 

[ 0 1 0 1 -1 1 -1] 

[ 0 0 1 0 -1 2 -1], 2), 

(-1.414213562373095?, Vector space of degree 7 and dimension 2 over Algebraic Field 

User basis matrix: 

[ 0 1 0 -1 0.4142135623730951? 1 -1] 

[ 0 0 1 0 -1 0 2.414213562373095?], 2), 

(1.414213562373095?, Vector space of degree 7 and dimension 2 over Algebraic Field 

User basis matrix: 

[ 0 1 0 -1 -2.414213562373095? 1 -1] 

[ 0 0 1 0 -1 0 -0.4142135623730951?], 2) 

] 

sage: A.eigenspaces_left(format='galois', algebraic_multiplicity=True) 

[ 

(3, Vector space of degree 7 and dimension 1 over Rational Field 

User basis matrix: 

[ 1 0 1/7 0 -1/7 0 -2/7], 1), 

(-2, Vector space of degree 7 and dimension 2 over Rational Field 

User basis matrix: 

[ 0 1 0 1 -1 1 -1] 

[ 0 0 1 0 -1 2 -1], 2), 

(a2, Vector space of degree 7 and dimension 2 over Number Field in a2 with defining polynomial x^2 - 2 

User basis matrix: 

[ 0 1 0 -1 -a2 - 1 1 -1] 

[ 0 0 1 0 -1 0 -a2 + 1], 2) 

] 

  

Next we compute the left eigenspaces over the finite field of order 11. :: 

  

sage: A = ModularSymbols(43, base_ring=GF(11), sign=1).T(2).matrix(); A 

[ 3 9 0 0] 

[ 0 9 0 1] 

[ 0 10 9 2] 

[ 0 9 0 2] 

sage: A.base_ring() 

Finite Field of size 11 

sage: A.charpoly() 

x^4 + 10*x^3 + 3*x^2 + 2*x + 1 

sage: A.eigenspaces_left(format='galois', var = 'beta') 

[ 

(9, Vector space of degree 4 and dimension 1 over Finite Field of size 11 

User basis matrix: 

[0 0 1 5]), 

(3, Vector space of degree 4 and dimension 1 over Finite Field of size 11 

User basis matrix: 

[1 6 0 6]), 

(beta2, Vector space of degree 4 and dimension 1 over Univariate Quotient Polynomial Ring in beta2 over Finite Field of size 11 with modulus x^2 + 9 

User basis matrix: 

[ 0 1 0 5*beta2 + 10]) 

] 

  

This method is only applicable to exact matrices. 

The "eigenmatrix" routines for matrices with double-precision 

floating-point entries (``RDF``, ``CDF``) are the best 

alternative. (Since some platforms return eigenvectors 

that are the negatives of those given here, this one example 

is not tested here.) There are also "eigenmatrix" routines for 

matrices with symbolic entries. :: 

  

sage: A = matrix(QQ, 3, 3, range(9)) 

sage: A.change_ring(RR).eigenspaces_left() 

Traceback (most recent call last): 

... 

NotImplementedError: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision, 

consult numerical or symbolic matrix classes for other options 

  

sage: em = A.change_ring(RDF).eigenmatrix_left() 

sage: eigenvalues = em[0]; eigenvalues.dense_matrix() # abs tol 1e-13 

[13.348469228349522 0.0 0.0] 

[ 0.0 -1.348469228349534 0.0] 

[ 0.0 0.0 0.0] 

sage: eigenvectors = em[1]; eigenvectors # not tested 

[ 0.440242867... 0.567868371... 0.695493875...] 

[ 0.897878732... 0.278434036... -0.341010658...] 

[ 0.408248290... -0.816496580... 0.408248290...] 

  

sage: x, y = var('x y') 

sage: S = matrix([[x, y], [y, 3*x^2]]) 

sage: em = S.eigenmatrix_left() 

sage: eigenvalues = em[0]; eigenvalues 

[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2) 0] 

[ 0 3/2*x^2 + 1/2*x + 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)] 

sage: eigenvectors = em[1]; eigenvectors 

[ 1 1/2*(3*x^2 - x - sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y] 

[ 1 1/2*(3*x^2 - x + sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y] 

  

A request for ``'all'`` the eigenvalues, when it is not 

possible, will raise an error. Using the ``'galois'`` 

format option is more likely to be successful. :: 

  

sage: F.<b> = FiniteField(11^2) 

sage: A = matrix(F, [[b + 1, b + 1], [10*b + 4, 5*b + 4]]) 

sage: A.eigenspaces_left(format='all') 

Traceback (most recent call last): 

... 

NotImplementedError: unable to construct eigenspaces for eigenvalues outside the base field, 

try the keyword option: format='galois' 

  

sage: A.eigenspaces_left(format='galois') 

[ 

(a0, Vector space of degree 2 and dimension 1 over Univariate Quotient Polynomial Ring in a0 over Finite Field in b of size 11^2 with modulus x^2 + (5*b + 6)*x + 8*b + 10 

User basis matrix: 

[ 1 6*b*a0 + 3*b + 1]) 

] 

  

TESTS: 

  

We make sure that :trac:`13308` is fixed. :: 

  

sage: M = ModularSymbols(Gamma1(23), sign=1) 

sage: m = M.cuspidal_subspace().hecke_matrix(2) 

sage: [j*m==i[0]*j for i in m.eigenspaces_left(format='all') for j in i[1].basis()] # long time (4s) 

[True, True, True, True, True, True, True, True, True, True, True, True] 

  

sage: B = matrix(QQ, 2, 3, range(6)) 

sage: B.eigenspaces_left() 

Traceback (most recent call last): 

... 

TypeError: matrix must be square, not 2 x 3 

  

sage: B = matrix(QQ, 4, 4, range(16)) 

sage: B.eigenspaces_left(format='junk') 

Traceback (most recent call last): 

... 

ValueError: format keyword must be None, 'all' or 'galois', not junk 

  

sage: B.eigenspaces_left(algebraic_multiplicity='garbage') 

Traceback (most recent call last): 

... 

ValueError: algebraic_multiplicity keyword must be True or False 

""" 

if not algebraic_multiplicity in [True, False]: 

msg = 'algebraic_multiplicity keyword must be True or False' 

raise ValueError(msg.format(algebraic_multiplicity)) 

if not self.is_square(): 

msg = 'matrix must be square, not {0} x {1}' 

raise TypeError(msg.format(self.nrows(), self.ncols())) 

if not self.base_ring().is_exact(): 

msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n", 

"consult numerical or symbolic matrix classes for other options") 

raise NotImplementedError(''.join(msg).format(self.base_ring())) 

  

format = self._eigenspace_format(format) 

  

key = 'eigenspaces_left_' + format + '{0}'.format(var) 

x = self.fetch(key) 

if not x is None: 

if algebraic_multiplicity: 

return x 

else: 

return Sequence([(e[0],e[1]) for e in x], cr=True, check=False) 

  

# Possible improvements: 

# algorithm for dual_eigenvector in sage/modular/hecke/module.py 

# use minpoly when algebraic_multiplicity=False 

# as of 2007-03-25 minpoly is unreliable via linbox 

  

import sage.categories.homset 

import sage.rings.qqbar 

  

G = self.fcp() # factored characteristic polynomial 

V = [] 

i = -1 # variable name index, increments for each eigenvalue 

for h, e in G: 

i = i + 1 

if h.degree() == 1: 

alpha = -h[0]/h[1] 

F = alpha.parent() 

if F != self.base_ring(): 

self = self.change_ring(F) 

A = self - alpha 

W = A.kernel() 

V.append((alpha, W.ambient_module().span_of_basis(W.basis()), e)) 

else: 

F = h.root_field('{0}{1}'.format(var,i)) 

alpha = F.gen(0) 

A = self.change_ring(F) - alpha 

W = A.kernel() 

WB = W.basis() 

if format == 'galois': 

V.append((alpha, W.ambient_module().span_of_basis(WB), e)) 

elif format == 'all': 

try: 

alpha_conj = alpha.galois_conjugates(sage.rings.qqbar.QQbar) 

except AttributeError: 

msg = ("unable to construct eigenspaces for eigenvalues outside the base field,\n" 

"try the keyword option: format='galois'") 

raise NotImplementedError(''.join(msg)) 

for ev in alpha_conj: 

m = sage.categories.homset.hom(alpha.parent(), ev.parent(), ev) 

space = (ev.parent())**self.nrows() 

evec_list = [(space)([m(v_j) for v_j in v]) for v in WB] 

V.append((ev, space.span_of_basis(evec_list, already_echelonized=True), e)) 

V = Sequence(V, cr=True, check=False) 

self.cache(key, V) 

if algebraic_multiplicity: 

return V 

else: 

return Sequence([(e[0],e[1]) for e in V], cr=True, check=False) 

  

left_eigenspaces = eigenspaces_left 

  

def eigenspaces_right(self, format='all', var='a', algebraic_multiplicity=False): 

r""" 

Compute the right eigenspaces of a matrix. 

  

Note that ``eigenspaces_right()`` and ``right_eigenspaces()`` 

are identical methods. Here "right" refers to the eigenvectors 

being placed to the right of the matrix. 

  

INPUT: 

  

- ``self`` - a square matrix over an exact field. For inexact 

matrices consult the numerical or symbolic matrix classes. 

  

- ``format`` - default: ``None`` 

  

- ``'all'`` - attempts to create every eigenspace. This will 

always be possible for matrices with rational entries. 

- ``'galois'`` - for each irreducible factor of the characteristic 

polynomial, a single eigenspace will be output for a 

single root/eigenvalue for the irreducible factor. 

- ``None`` - Uses the 'all' format if the base ring is contained 

in an algebraically closed field which is implemented. 

Otherwise, uses the 'galois' format. 

  

- ``var`` - default: 'a' - variable name used to 

represent elements of the root field of each 

irreducible factor of the characteristic polynomial. 

If var='a', then the root fields will be in terms of 

a0, a1, a2, ...., where the numbering runs across all 

the irreducible factors of the characteristic polynomial, 

even for linear factors. 

  

- ``algebraic_multiplicity`` - default: False - whether or 

not to include the algebraic multiplicity of each eigenvalue 

in the output. See the discussion below. 

  

OUTPUT: 

  

If algebraic_multiplicity=False, return a list of pairs (e, V) 

where e is an eigenvalue of the matrix, and V is the corresponding 

left eigenspace. For Galois conjugates of eigenvalues, there 

may be just one representative eigenspace, depending on the 

``format`` keyword. 

  

If algebraic_multiplicity=True, return a list of triples (e, V, n) 

where e and V are as above and n is the algebraic multiplicity of 

the eigenvalue. 

  

.. warning:: 

  

Uses a somewhat naive algorithm (simply factors the 

characteristic polynomial and computes kernels directly 

over the extension field). 

  

EXAMPLES: 

  

Right eigenspaces are computed from the left eigenspaces of the 

transpose of the matrix. As such, there is a greater collection 

of illustrative examples at the :meth:`eigenspaces_left`. 

  

We compute the right eigenspaces of a `3\times 3` rational matrix. :: 

  

sage: A = matrix(QQ, 3 ,3, range(9)); A 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: A.eigenspaces_right() 

[ 

(0, Vector space of degree 3 and dimension 1 over Rational Field 

User basis matrix: 

[ 1 -2 1]), 

(-1.348469228349535?, Vector space of degree 3 and dimension 1 over Algebraic Field 

User basis matrix: 

[ 1 0.1303061543300932? -0.7393876913398137?]), 

(13.34846922834954?, Vector space of degree 3 and dimension 1 over Algebraic Field 

User basis matrix: 

[ 1 3.069693845669907? 5.139387691339814?]) 

] 

sage: es = A.eigenspaces_right(format='galois'); es 

[ 

(0, Vector space of degree 3 and dimension 1 over Rational Field 

User basis matrix: 

[ 1 -2 1]), 

(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 

User basis matrix: 

[ 1 1/5*a1 + 2/5 2/5*a1 - 1/5]) 

] 

sage: es = A.eigenspaces_right(format='galois', algebraic_multiplicity=True); es 

[ 

(0, Vector space of degree 3 and dimension 1 over Rational Field 

User basis matrix: 

[ 1 -2 1], 1), 

(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 

User basis matrix: 

[ 1 1/5*a1 + 2/5 2/5*a1 - 1/5], 1) 

] 

sage: e, v, n = es[0]; v = v.basis()[0] 

sage: delta = v*e - A*v 

sage: abs(abs(delta)) < 1e-10 

True 

  

The same computation, but with implicit base change to a field:: 

  

sage: A = matrix(ZZ, 3, range(9)); A 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: A.eigenspaces_right(format='galois') 

[ 

(0, Vector space of degree 3 and dimension 1 over Rational Field 

User basis matrix: 

[ 1 -2 1]), 

(a1, Vector space of degree 3 and dimension 1 over Number Field in a1 with defining polynomial x^2 - 12*x - 18 

User basis matrix: 

[ 1 1/5*a1 + 2/5 2/5*a1 - 1/5]) 

] 

  

This method is only applicable to exact matrices. 

The "eigenmatrix" routines for matrices with double-precision 

floating-point entries (``RDF``, ``CDF``) are the best 

alternative. (Since some platforms return eigenvectors 

that are the negatives of those given here, this one example 

is not tested here.) There are also "eigenmatrix" routines for 

matrices with symbolic entries. :: 

  

sage: B = matrix(RR, 3, 3, range(9)) 

sage: B.eigenspaces_right() 

Traceback (most recent call last): 

... 

NotImplementedError: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision, 

consult numerical or symbolic matrix classes for other options 

  

sage: em = B.change_ring(RDF).eigenmatrix_right() 

sage: eigenvalues = em[0]; eigenvalues.dense_matrix() # abs tol 1e-13 

[13.348469228349522 0.0 0.0] 

[ 0.0 -1.348469228349534 0.0] 

[ 0.0 0.0 0.0] 

sage: eigenvectors = em[1]; eigenvectors # not tested 

[ 0.164763817... 0.799699663... 0.408248290...] 

[ 0.505774475... 0.104205787... -0.816496580...] 

[ 0.846785134... -0.591288087... 0.408248290...] 

  

sage: x, y = var('x y') 

sage: S = matrix([[x, y], [y, 3*x^2]]) 

sage: em = S.eigenmatrix_right() 

sage: eigenvalues = em[0]; eigenvalues 

[3/2*x^2 + 1/2*x - 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2) 0] 

[ 0 3/2*x^2 + 1/2*x + 1/2*sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2)] 

sage: eigenvectors = em[1]; eigenvectors 

[ 1 1] 

[1/2*(3*x^2 - x - sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y 1/2*(3*x^2 - x + sqrt(9*x^4 - 6*x^3 + x^2 + 4*y^2))/y] 

  

TESTS:: 

  

sage: B = matrix(QQ, 2, 3, range(6)) 

sage: B.eigenspaces_right() 

Traceback (most recent call last): 

... 

TypeError: matrix must be square, not 2 x 3 

  

sage: B = matrix(QQ, 4, 4, range(16)) 

sage: B.eigenspaces_right(format='junk') 

Traceback (most recent call last): 

... 

ValueError: format keyword must be None, 'all' or 'galois', not junk 

  

sage: B.eigenspaces_right(algebraic_multiplicity='garbage') 

Traceback (most recent call last): 

... 

ValueError: algebraic_multiplicity keyword must be True or False 

""" 

if not algebraic_multiplicity in [True, False]: 

msg = 'algebraic_multiplicity keyword must be True or False' 

raise ValueError(msg.format(algebraic_multiplicity)) 

if not self.is_square(): 

msg = 'matrix must be square, not {0} x {1}' 

raise TypeError(msg.format(self.nrows(), self.ncols())) 

if not self.base_ring().is_exact(): 

msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n", 

"consult numerical or symbolic matrix classes for other options") 

raise NotImplementedError(''.join(msg).format(self.base_ring())) 

  

format = self._eigenspace_format(format) 

  

key = 'eigenspaces_right_' + format + '{0}'.format(var) 

x = self.fetch(key) 

if not x is None: 

if algebraic_multiplicity: 

return x 

else: 

return Sequence([(e[0],e[1]) for e in x], cr=True, check=False) 

  

V = self.transpose().eigenspaces_left(format=format, var=var, algebraic_multiplicity=True) 

  

self.cache(key, V) 

if algebraic_multiplicity: 

return V 

else: 

return Sequence([(e[0],e[1]) for e in V], cr=True, check=False) 

  

right_eigenspaces = eigenspaces_right 

  

def eigenvalues(self,extend=True): 

r""" 

Return a sequence of the eigenvalues of a matrix, with 

multiplicity. If the eigenvalues are roots of polynomials in QQ, 

then QQbar elements are returned that represent each separate 

root. 

  

If the option extend is set to False, only eigenvalues in the base 

ring are considered. 

  

EXAMPLES:: 

  

sage: a = matrix(ZZ, 4, range(16)); a 

[ 0 1 2 3] 

[ 4 5 6 7] 

[ 8 9 10 11] 

[12 13 14 15] 

sage: sorted(a.eigenvalues(), reverse=True) 

[32.46424919657298?, 0, 0, -2.464249196572981?] 

  

:: 

  

sage: a=matrix([(1, 9, -1, -1), (-2, 0, -10, 2), (-1, 0, 15, -2), (0, 1, 0, -1)]) 

sage: a.eigenvalues() 

[-0.9386318578049146?, 15.50655435353258?, 0.2160387521361705? - 4.713151979747493?*I, 0.2160387521361705? + 4.713151979747493?*I] 

  

A symmetric matrix a+a.transpose() should have real eigenvalues 

  

:: 

  

sage: b=a+a.transpose() 

sage: ev = b.eigenvalues(); ev 

[-8.35066086057957?, -1.107247901349379?, 5.718651326708515?, 33.73925743522043?] 

  

The eigenvalues are elements of QQbar, so they really represent 

exact roots of polynomials, not just approximations. 

  

:: 

  

sage: e = ev[0]; e 

-8.35066086057957? 

sage: p = e.minpoly(); p 

x^4 - 30*x^3 - 171*x^2 + 1460*x + 1784 

sage: p(e) == 0 

True 

  

To perform computations on the eigenvalue as an element of a number 

field, you can always convert back to a number field element. 

  

:: 

  

sage: e.as_number_field_element() 

(Number Field in a with defining polynomial y^4 - 2*y^3 - 507*y^2 - 3972*y - 4264, 

a + 7, 

Ring morphism: 

From: Number Field in a with defining polynomial y^4 - 2*y^3 - 507*y^2 - 3972*y - 4264 

To: Algebraic Real Field 

Defn: a |--> -15.35066086057957?) 

  

Notice the effect of the extend option. 

  

:: 

  

sage: M=matrix(QQ,[[0,-1,0],[1,0,0],[0,0,2]]) 

sage: M.eigenvalues() 

[2, -1*I, 1*I] 

sage: M.eigenvalues(extend=False) 

[2] 

  

The method also works for matrices over finite fields:: 

  

sage: M = matrix(GF(3), [[0,1,1],[1,2,0],[2,0,1]]) 

sage: ev = sorted(M.eigenvalues()); ev 

[2*z3, 2*z3 + 1, 2*z3 + 2] 

  

Similarly as in the case of QQbar, the eigenvalues belong to some 

algebraic closure but they can be converted to elements of a finite 

field:: 

  

sage: e = ev[0] 

sage: e.parent() 

Algebraic closure of Finite Field of size 3 

sage: e.as_finite_field_element() 

(Finite Field in z3 of size 3^3, 2*z3, Ring morphism: 

From: Finite Field in z3 of size 3^3 

To: Algebraic closure of Finite Field of size 3 

Defn: z3 |--> z3) 

""" 

x = self.fetch('eigenvalues') 

if x is not None: 

if not extend: 

x = Sequence(i for i in x if i in self.base_ring()) 

return x 

  

if not self.base_ring().is_exact(): 

from warnings import warn 

warn("Using generic algorithm for an inexact ring, which will probably give incorrect results due to numerical precision issues.") 

  

if not extend: 

return Sequence(r for r,m in self.charpoly().roots() for _ in xrange(m)) 

  

# now we need to find a natural algebraic closure for the base ring 

K = self.base_ring() 

try: 

is_field = K.is_field() 

except (ValueError, AttributeError): 

is_field = False 

  

if not is_field: 

if not K.is_integral_domain(): 

raise NotImplementedError("eigenvalues() not implemented for non integral domains") 

K = K.fraction_field() 

  

try: 

A = K.algebraic_closure() 

except (AttributeError, ValueError): 

raise NotImplementedError("algebraic closure is not implemented for %s" % K) 

  

res = [] 

for f, e in self.charpoly().change_ring(K).factor(): 

if f.degree() == 1: 

res.extend([-f.constant_coefficient()]*e) 

else: 

for r,ee in f.change_ring(A).roots(): 

res.extend([r]*(e*ee)) 

  

eigenvalues = Sequence(res) 

self.cache('eigenvalues', eigenvalues) 

return eigenvalues 

  

def eigenvectors_left(self,extend=True): 

r""" 

Compute the left eigenvectors of a matrix. 

  

For each distinct eigenvalue, returns a list of the form (e,V,n) 

where e is the eigenvalue, V is a list of eigenvectors forming a 

basis for the corresponding left eigenspace, and n is the algebraic 

multiplicity of the eigenvalue. 

  

If the option extend is set to False, then only the eigenvalues that 

live in the base ring are considered. 

  

EXAMPLES: We compute the left eigenvectors of a `3\times 3` 

rational matrix. 

  

:: 

  

sage: A = matrix(QQ,3,3,range(9)); A 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: es = A.eigenvectors_left(); es 

[(0, [ 

(1, -2, 1) 

], 1), 

(-1.348469228349535?, [(1, 0.3101020514433644?, -0.3797958971132713?)], 1), 

(13.34846922834954?, [(1, 1.289897948556636?, 1.579795897113272?)], 1)] 

sage: eval, [evec], mult = es[0] 

sage: delta = eval*evec - evec*A 

sage: abs(abs(delta)) < 1e-10 

True 

  

Notice the difference between considering ring extensions or not. 

  

:: 

  

sage: M=matrix(QQ,[[0,-1,0],[1,0,0],[0,0,2]]) 

sage: M.eigenvectors_left() 

[(2, [ 

(0, 0, 1) 

], 1), (-1*I, [(1, -1*I, 0)], 1), (1*I, [(1, 1*I, 0)], 1)] 

sage: M.eigenvectors_left(extend=False) 

[(2, [ 

(0, 0, 1) 

], 1)] 

  

""" 

x = self.fetch('eigenvectors_left') 

if not x is None: 

return x 

  

if not self.base_ring().is_exact(): 

from warnings import warn 

warn("Using generic algorithm for an inexact ring, which may result in garbage from numerical precision issues.") 

  

V = [] 

from sage.rings.qqbar import QQbar 

from sage.categories.homset import hom 

eigenspaces = self.eigenspaces_left(format='galois', algebraic_multiplicity=True) 

evec_list=[] 

n = self._nrows 

evec_eval_list = [] 

F = self.base_ring().fraction_field() 

for ev in eigenspaces: 

eigval = ev[0] 

eigbasis = ev[1].basis() 

eigmult = ev[2] 

if eigval in self.base_ring() or extend: 

if eigval.parent().fraction_field() == F: 

evec_eval_list.append((eigval, eigbasis, eigmult)) 

else: 

try: 

eigval_conj = eigval.galois_conjugates(QQbar) 

except AttributeError: 

raise NotImplementedError("eigenvectors are not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar") 

  

for e in eigval_conj: 

m = hom(eigval.parent(), e.parent(), e) 

space = (e.parent())**n 

evec_list = [(space)([m(i) for i in v]) for v in eigbasis] 

evec_eval_list.append( (e, evec_list, eigmult)) 

  

return evec_eval_list 

  

left_eigenvectors = eigenvectors_left 

  

def eigenvectors_right(self, extend=True): 

r""" 

Compute the right eigenvectors of a matrix. 

  

For each distinct eigenvalue, returns a list of the form (e,V,n) 

where e is the eigenvalue, V is a list of eigenvectors forming a 

basis for the corresponding right eigenspace, and n is the 

algebraic multiplicity of the eigenvalue. If ``extend = True`` 

(the default), this will return eigenspaces over the algebraic 

closure of the base field where this is implemented; otherwise 

it will restrict to eigenvalues in the base field. 

  

EXAMPLES: We compute the right eigenvectors of a 

`3\times 3` rational matrix. 

  

:: 

  

sage: A = matrix(QQ,3,3,range(9)); A 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: es = A.eigenvectors_right(); es 

[(0, [ 

(1, -2, 1) 

], 1), 

(-1.348469228349535?, [(1, 0.1303061543300932?, -0.7393876913398137?)], 1), 

(13.34846922834954?, [(1, 3.069693845669907?, 5.139387691339814?)], 1)] 

sage: A.eigenvectors_right(extend=False) 

[(0, [ 

(1, -2, 1) 

], 1)] 

sage: eval, [evec], mult = es[0] 

sage: delta = eval*evec - A*evec 

sage: abs(abs(delta)) < 1e-10 

True 

""" 

return self.transpose().eigenvectors_left(extend=extend) 

  

right_eigenvectors = eigenvectors_right 

  

def eigenmatrix_left(self): 

r""" 

Return matrices D and P, where D is a diagonal matrix of 

eigenvalues and P is the corresponding matrix where the rows are 

corresponding eigenvectors (or zero vectors) so that P\*self = 

D\*P. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ,3,3,range(9)); A 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: D, P = A.eigenmatrix_left() 

sage: D 

[ 0 0 0] 

[ 0 -1.348469228349535? 0] 

[ 0 0 13.34846922834954?] 

sage: P 

[ 1 -2 1] 

[ 1 0.3101020514433644? -0.3797958971132713?] 

[ 1 1.289897948556636? 1.579795897113272?] 

sage: P*A == D*P 

True 

  

Because P is invertible, A is diagonalizable. 

  

:: 

  

sage: A == (~P)*D*P 

True 

  

The matrix P may contain zero rows corresponding to eigenvalues for 

which the algebraic multiplicity is greater than the geometric 

multiplicity. In these cases, the matrix is not diagonalizable. 

  

:: 

  

sage: A = jordan_block(2,3); A 

[2 1 0] 

[0 2 1] 

[0 0 2] 

sage: A = jordan_block(2,3) 

sage: D, P = A.eigenmatrix_left() 

sage: D 

[2 0 0] 

[0 2 0] 

[0 0 2] 

sage: P 

[0 0 1] 

[0 0 0] 

[0 0 0] 

sage: P*A == D*P 

True 

  

TESTS: 

  

For matrices with floating point entries, some platforms will 

return eigenvectors that are negatives of those returned by the 

majority of platforms. This test accounts for that possibility. 

Running this test independently, without adjusting the eigenvectors 

could indicate this situation on your hardware. :: 

  

sage: A = matrix(QQ, 3, 3, range(9)) 

sage: em = A.change_ring(RDF).eigenmatrix_left() 

sage: evalues = em[0]; evalues.dense_matrix() # abs tol 1e-13 

[13.348469228349522 0.0 0.0] 

[ 0.0 -1.348469228349534 0.0] 

[ 0.0 0.0 0.0] 

sage: evectors = em[1]; 

sage: for i in range(3): 

....: scale = evectors[i,0].sign() 

....: evectors.rescale_row(i, scale) 

sage: evectors # abs tol 1e-13 

[0.44024286723591904 0.5678683713143027 0.6954938753926869] 

[ 0.8978787322617111 0.27843403682172374 -0.3410106586182631] 

[ 0.4082482904638625 -0.8164965809277263 0.40824829046386324] 

  

The following example shows that :trac:`20439` has been resolved:: 

  

sage: A = matrix(CDF, [[-2.53634347567, 2.04801738686, -0.0, -62.166145304], 

....: [ 0.7, -0.6, 0.0, 0.0], 

....: [0.547271128842, 0.0, -0.3015, -21.7532081652], 

....: [0.0, 0.0, 0.3, -0.4]]) 

sage: D, P = A.eigenmatrix_left() 

sage: (P*A - D*P).norm() < 10^(-2) 

True 

  

The following example shows that the fix for :trac:`20439` (conjugating 

eigenvectors rather than eigenvalues) is the correct one:: 

  

sage: A = Matrix(CDF,[[I,0],[0,1]]) 

sage: D, P = A.eigenmatrix_left() 

sage: (P*A - D*P).norm() < 10^(-2) 

True 

""" 

from sage.misc.flatten import flatten 

from sage.matrix.constructor import diagonal_matrix, matrix 

evecs = self.eigenvectors_left() 

D = diagonal_matrix(flatten([[e[0]]*e[2] for e in evecs])) 

rows = [] 

for e in evecs: 

rows.extend(e[1]+[e[1][0].parent().zero_vector()]*(e[2]-len(e[1]))) 

P = matrix(rows) 

return D,P 

  

left_eigenmatrix = eigenmatrix_left 

  

def eigenmatrix_right(self): 

r""" 

Return matrices D and P, where D is a diagonal matrix of 

eigenvalues and P is the corresponding matrix where the columns are 

corresponding eigenvectors (or zero vectors) so that self\*P = 

P\*D. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ,3,3,range(9)); A 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: D, P = A.eigenmatrix_right() 

sage: D 

[ 0 0 0] 

[ 0 -1.348469228349535? 0] 

[ 0 0 13.34846922834954?] 

sage: P 

[ 1 1 1] 

[ -2 0.1303061543300932? 3.069693845669907?] 

[ 1 -0.7393876913398137? 5.139387691339814?] 

sage: A*P == P*D 

True 

  

Because P is invertible, A is diagonalizable. 

  

:: 

  

sage: A == P*D*(~P) 

True 

  

The matrix P may contain zero columns corresponding to eigenvalues 

for which the algebraic multiplicity is greater than the geometric 

multiplicity. In these cases, the matrix is not diagonalizable. 

  

:: 

  

sage: A = jordan_block(2,3); A 

[2 1 0] 

[0 2 1] 

[0 0 2] 

sage: A = jordan_block(2,3) 

sage: D, P = A.eigenmatrix_right() 

sage: D 

[2 0 0] 

[0 2 0] 

[0 0 2] 

sage: P 

[1 0 0] 

[0 0 0] 

[0 0 0] 

sage: A*P == P*D 

True 

  

TESTS: 

  

For matrices with floating point entries, some platforms will 

return eigenvectors that are negatives of those returned by the 

majority of platforms. This test accounts for that possibility. 

Running this test independently, without adjusting the eigenvectors 

could indicate this situation on your hardware. :: 

  

sage: B = matrix(QQ, 3, 3, range(9)) 

sage: em = B.change_ring(RDF).eigenmatrix_right() 

sage: evalues = em[0]; evalues.dense_matrix() # abs tol 1e-13 

[13.348469228349522 0.0 0.0] 

[ 0.0 -1.348469228349534 0.0] 

[ 0.0 0.0 0.0] 

sage: evectors = em[1]; 

sage: for i in range(3): 

....: scale = evectors[0,i].sign() 

....: evectors.rescale_col(i, scale) 

sage: evectors # abs tol 1e-13 

[ 0.1647638172823028 0.799699663111865 0.40824829046386285] 

[ 0.5057744759005657 0.10420578771917821 -0.8164965809277261] 

[ 0.8467851345188293 -0.5912880876735089 0.4082482904638632] 

  

The following example shows that :trac:`20439` has been resolved:: 

  

sage: A = matrix(CDF, [[-2.53634347567, 2.04801738686, -0.0, -62.166145304], 

....: [ 0.7, -0.6, 0.0, 0.0], 

....: [0.547271128842, 0.0, -0.3015, -21.7532081652], 

....: [0.0, 0.0, 0.3, -0.4]]) 

sage: D, P = A.eigenmatrix_right() 

sage: (A*P - P*D).norm() < 10^(-2) 

True 

  

The following example shows that the fix for :trac:`20439` (conjugating 

eigenvectors rather than eigenvalues) is the correct one:: 

  

sage: A = Matrix(CDF,[[I,0],[0,1]]) 

sage: D, P = A.eigenmatrix_right() 

sage: (A*P - P*D).norm() < 10^(-2) 

True 

  

""" 

D,P = self.transpose().eigenmatrix_left() 

return D,P.transpose() 

  

right_eigenmatrix = eigenmatrix_right 

  

def eigenvalue_multiplicity(self, s): 

r""" 

Return the multiplicity of ``s`` as a generalized eigenvalue 

of the matrix. 

  

EXAMPLES:: 

  

sage: M = Matrix(QQ, [[0,1],[0,0]]) 

sage: M.eigenvalue_multiplicity(0) 

2 

sage: M.eigenvalue_multiplicity(1) 

0 

  

sage: M = posets.DiamondPoset(5).coxeter_transformation() 

sage: [M.eigenvalue_multiplicity(x) for x in [-1, 1]] 

[3, 2] 

  

TESTS:: 

  

sage: M = Matrix(QQ, [[0,1,2],[0,0,0]]) 

sage: M.eigenvalue_multiplicity(1) 

Traceback (most recent call last): 

... 

TypeError: matrix must be square, not 2 x 3 

""" 

if not self.is_square(): 

msg = 'matrix must be square, not {0} x {1}' 

raise TypeError(msg.format(self.nrows(), self.ncols())) 

  

r = self.dimensions()[0] 

n = 0 

m1 = self - s 

while True: 

m1 *= m1 

m2 = m1.extended_echelon_form(subdivide=True) 

t = r - m2.subdivisions()[0][0] 

n += t 

if t == 0 or t == r: 

return n 

m3 = m2.subdivision(0, 0) 

m4 = m2.submatrix(0, r, r, r) 

m5 = m3 * m4.inverse() 

m1 = m5.submatrix(0, 0, r - t, r - t) 

r -= t 

  

##################################################################################### 

# Generic Echelon Form 

################################################################################### 

  

def rref(self, *args, **kwds): 

""" 

Return the reduced row echelon form of the matrix, considered 

as a matrix over a field. 

  

If the matrix is over a ring, then an equivalent matrix is 

constructed over the fraction field, and then row reduced. 

  

All arguments are passed on to :meth:`echelon_form`. 

  

.. NOTE:: 

  

Because the matrix is viewed as a matrix over a field, 

every leading coefficient of the returned matrix will be 

one and will be the only nonzero entry in its column. 

  

EXAMPLES:: 

  

sage: A=matrix(3,range(9)); A 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: A.rref() 

[ 1 0 -1] 

[ 0 1 2] 

[ 0 0 0] 

  

  

Note that there is a difference between :meth:`rref` and 

:meth:`echelon_form` when the matrix is not over a field (in 

this case, the integers instead of the rational numbers):: 

  

sage: A.base_ring() 

Integer Ring 

sage: A.echelon_form() 

[ 3 0 -3] 

[ 0 1 2] 

[ 0 0 0] 

  

sage: B=random_matrix(QQ,3,num_bound=10); B 

[ -4 -3 6] 

[ 5 -5 9/2] 

[3/2 -4 -7] 

sage: B.rref() 

[1 0 0] 

[0 1 0] 

[0 0 1] 

  

In this case, since ``B`` is a matrix over a field (the 

rational numbers), :meth:`rref` and :meth:`echelon_form` are 

exactly the same:: 

  

sage: B.echelon_form() 

[1 0 0] 

[0 1 0] 

[0 0 1] 

sage: B.echelon_form() is B.rref() 

True 

  

Since :meth:`echelon_form` is not implemented for every ring, 

sometimes behavior varies, as here:: 

  

sage: R.<x>=ZZ[] 

sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1,3,2,1]) 

sage: C.rref() 

[1 0 0] 

[0 1 0] 

[0 0 1] 

sage: C.base_ring() 

Univariate Polynomial Ring in x over Integer Ring 

sage: C.echelon_form() 

Traceback (most recent call last): 

... 

NotImplementedError: Ideal Ideal (2, x + 1) of Univariate Polynomial Ring in x over Integer Ring not principal 

Echelon form not implemented over 'Univariate Polynomial Ring in x over Integer Ring'. 

sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1,3,2,1/2]) 

sage: C.echelon_form() 

[ 2 x x^2] 

[ 0 1 15*x^2 - 3/2*x - 31/2] 

[ 0 0 5/2*x^3 - 15/4*x^2 - 9/4*x + 7/2] 

sage: C.rref() 

[1 0 0] 

[0 1 0] 

[0 0 1] 

sage: C = matrix(3,[2,x,x^2,x+1,3-x,-1/x,3,2,1/2]) 

sage: C.echelon_form() 

[1 0 0] 

[0 1 0] 

[0 0 1] 

""" 

R=self.base_ring() 

if R.is_field(): 

return self.echelon_form() 

else: 

F=R.fraction_field() 

return self.change_ring(F).echelon_form() 

  

def _echelonize_ring(self, **kwds): 

r""" 

Echelonize self in place, where the base ring of self is assumed to 

be a ring (not a field). 

  

Right now this *only* works over ZZ and some principal ideal domains; 

otherwise a ``NotImplementedError`` is raised. In the special case of 

sparse matrices over ZZ it makes them dense, gets the echelon form of 

the dense matrix, then sets self equal to the result. 

  

EXAMPLES:: 

  

sage: a = matrix(ZZ, 3, 4, [1..12], sparse=True); a 

[ 1 2 3 4] 

[ 5 6 7 8] 

[ 9 10 11 12] 

sage: a._echelonize_ring() 

sage: a 

[ 1 2 3 4] 

[ 0 4 8 12] 

[ 0 0 0 0] 

  

sage: L.<w> = NumberField(x^2 - x + 2) 

sage: OL = L.ring_of_integers() 

sage: m = matrix(OL, 2, 2, [1,2,3,4+w]) 

sage: m.echelon_form() 

[ 1 2] 

[ 0 w - 2] 

sage: E, T = m.echelon_form(transformation=True); E,T 

( 

[ 1 2] [ 1 0] 

[ 0 w - 2], [-3 1] 

) 

sage: E == T*m 

True 

  

TESTS: 

  

Check that http://trac.sagemath.org/sage_trac/ticket/11558 is fixed:: 

  

sage: matrix(ZZ, [[1,2],[4,6]], sparse=False).echelon_form(transformation=True) 

( 

[1 0] [-3 1] 

[0 2], [ 4 -1] 

) 

sage: matrix(ZZ, [[1,2],[4,6]], sparse=True).echelon_form(transformation=True) 

( 

[1 0] [-3 1] 

[0 2], [ 4 -1] 

) 

""" 

self.check_mutability() 

cdef Matrix d, a 

cdef Py_ssize_t r, c 

cdef bint transformation = 'transformation' in kwds and kwds['transformation'] 

if self._base_ring == ZZ: 

if 'include_zero_rows' in kwds and not kwds['include_zero_rows']: 

raise ValueError("cannot echelonize in place and delete zero rows") 

if transformation: 

d, a = self.dense_matrix().echelon_form(**kwds) 

else: 

d = self.dense_matrix().echelon_form(**kwds) 

for c from 0 <= c < self.ncols(): 

for r from 0 <= r < self.nrows(): 

self.set_unsafe(r, c, d.get_unsafe(r,c)) 

self.clear_cache() 

self.cache('pivots', d.pivots()) 

self.cache('in_echelon_form', True) 

else: 

try: 

a, d, p = self._echelon_form_PID() 

except TypeError as msg: 

raise NotImplementedError("%s\nechelon form over %s not yet implemented"%(msg, self.base_ring())) 

  

for c from 0 <= c < self.ncols(): 

for r from 0 <= r < self.nrows(): 

self.set_unsafe(r, c, d.get_unsafe(r,c)) 

self.clear_cache() 

self.cache('pivots', tuple(p)) 

self.cache('in_echelon_form', True) 

if transformation: 

return a 

else: 

return 

  

def echelonize(self, algorithm="default", cutoff=0, **kwds): 

r""" 

Transform ``self`` into a matrix in echelon form over the same 

base ring as self. 

  

.. NOTE:: 

  

This row reduction does not use division if the 

matrix is not over a field (e.g., if the matrix is over 

the integers). If you want to calculate the echelon form 

using division, then use :meth:`rref`, which assumes that 

the matrix entries are in a field (specifically, the field 

of fractions of the base ring of the matrix). 

  

INPUT: 

  

- ``algorithm`` -- string. Which algorithm to use. Choices are 

  

- ``'default'``: Let Sage choose an algorithm (default). 

  

- ``'classical'``: Gauss elimination. 

  

- ``'strassen'``: use a Strassen divide and conquer 

algorithm (if available) 

  

- ``cutoff`` -- integer. Only used if the Strassen algorithm 

is selected. 

  

- ``transformation`` -- boolean. Whether to also return the 

transformation matrix. Some matrix backends do not provide 

this information, in which case this option is ignored. 

  

OUTPUT: 

  

The matrix ``self`` is put into echelon form. Nothing is 

returned unless the keyword option ``transformation=True`` is 

specified, in which case the transformation matrix is 

returned. 

  

EXAMPLES:: 

  

sage: a = matrix(QQ,3,3,range(9)); a 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: a.echelonize() 

sage: a 

[ 1 0 -1] 

[ 0 1 2] 

[ 0 0 0] 

  

An immutable matrix cannot be transformed into echelon form. Use 

``self.echelon_form()`` instead:: 

  

sage: a = matrix(QQ,3,3,range(9)); a.set_immutable() 

sage: a.echelonize() 

Traceback (most recent call last): 

... 

ValueError: matrix is immutable; please change a copy instead 

(i.e., use copy(M) to change a copy of M). 

sage: a.echelon_form() 

[ 1 0 -1] 

[ 0 1 2] 

[ 0 0 0] 

  

Echelon form over the integers is what is also classically often 

known as Hermite normal form:: 

  

sage: a = matrix(ZZ,3,3,range(9)) 

sage: a.echelonize(); a 

[ 3 0 -3] 

[ 0 1 2] 

[ 0 0 0] 

  

We compute an echelon form both over a domain and fraction field:: 

  

sage: R.<x,y> = QQ[] 

sage: a = matrix(R, 2, [x,y,x,y]) 

sage: a.echelon_form() # not very useful? -- why two copies of the same row? 

[x y] 

[x y] 

  

:: 

  

sage: b = a.change_ring(R.fraction_field()) 

sage: b.echelon_form() # potentially useful 

[ 1 y/x] 

[ 0 0] 

  

Echelon form is not defined over arbitrary rings:: 

  

sage: a = matrix(Integers(9),3,3,range(9)) 

sage: a.echelon_form() 

Traceback (most recent call last): 

... 

NotImplementedError: Echelon form not implemented over 'Ring of integers modulo 9'. 

  

Involving a sparse matrix:: 

  

sage: m = matrix(3,[1, 1, 1, 1, 0, 2, 1, 2, 0], sparse=True); m 

[1 1 1] 

[1 0 2] 

[1 2 0] 

sage: m.echelon_form() 

[ 1 0 2] 

[ 0 1 -1] 

[ 0 0 0] 

sage: m.echelonize(); m 

[ 1 0 2] 

[ 0 1 -1] 

[ 0 0 0] 

  

The transformation matrix is optionally returned:: 

  

sage: m_original = m 

sage: transformation_matrix = m.echelonize(transformation=True) 

sage: m == transformation_matrix * m_original 

True 

""" 

self.check_mutability() 

  

if algorithm == 'default': 

if self._will_use_strassen_echelon(): 

algorithm = 'strassen' 

else: 

algorithm = 'classical' 

try: 

if self.base_ring().is_field(): 

if algorithm == 'classical': 

self._echelon_in_place_classical() 

elif algorithm == 'strassen': 

self._echelon_strassen(cutoff) 

else: 

raise ValueError("Unknown algorithm '%s'" % algorithm) 

else: 

if not (algorithm in ['classical', 'strassen']): 

kwds['algorithm'] = algorithm 

return self._echelonize_ring(**kwds) 

except ArithmeticError as msg: 

raise NotImplementedError("%s\nEchelon form not implemented over '%s'."%(msg,self.base_ring())) 

  

def echelon_form(self, algorithm="default", cutoff=0, **kwds): 

""" 

Return the echelon form of self. 

  

.. NOTE:: 

  

This row reduction does not use division if the 

matrix is not over a field (e.g., if the matrix is over 

the integers). If you want to calculate the echelon form 

using division, then use :meth:`rref`, which assumes that 

the matrix entries are in a field (specifically, the field 

of fractions of the base ring of the matrix). 

  

INPUT: 

  

- ``algorithm`` -- string. Which algorithm to use. Choices are 

  

- ``'default'``: Let Sage choose an algorithm (default). 

  

- ``'classical'``: Gauss elimination. 

  

- ``'strassen'``: use a Strassen divide and conquer 

algorithm (if available) 

  

- ``cutoff`` -- integer. Only used if the Strassen algorithm is selected. 

  

- ``transformation`` -- boolean. Whether to also return the 

transformation matrix. Some matrix backends do not provide 

this information, in which case this option is ignored. 

  

OUTPUT: 

  

The reduced row echelon form of ``self``, as an immutable 

matrix. Note that self is *not* changed by this command. Use 

:meth:`echelonize` to change ``self`` in place. 

  

If the optional parameter ``transformation=True`` is 

specified, the output consists of a pair `(E,T)` of matrices 

where `E` is the echelon form of ``self`` and `T` is the 

transformation matrix. 

  

EXAMPLES:: 

  

sage: MS = MatrixSpace(GF(19),2,3) 

sage: C = MS.matrix([1,2,3,4,5,6]) 

sage: C.rank() 

2 

sage: C.nullity() 

0 

sage: C.echelon_form() 

[ 1 0 18] 

[ 0 1 2] 

  

The matrix library used for `\ZZ/p`-matrices does not return 

the transformation matrix, so the ``transformation`` option is 

ignored:: 

  

sage: C.echelon_form(transformation=True) 

[ 1 0 18] 

[ 0 1 2] 

  

sage: D = matrix(ZZ, 2, 3, [1,2,3,4,5,6]) 

sage: D.echelon_form(transformation=True) 

( 

[1 2 3] [ 1 0] 

[0 3 6], [ 4 -1] 

) 

sage: E, T = D.echelon_form(transformation=True) 

sage: T*D == E 

True 

""" 

cdef bint transformation = ('transformation' in kwds and kwds['transformation']) 

x = self.fetch('echelon_form') 

if x is not None: 

if not transformation: 

return x 

y = self.fetch('echelon_transformation') 

if y: 

return (x, y) 

  

E = self.__copy__() 

if algorithm == 'default': 

v = E.echelonize(cutoff=cutoff, **kwds) 

else: 

v = E.echelonize(algorithm = algorithm, cutoff=cutoff, **kwds) 

E.set_immutable() # so we can cache the echelon form. 

self.cache('echelon_form', E) 

if v is not None: 

self.cache('echelon_transformation', v) 

self.cache('pivots', E.pivots()) 

if transformation and v is not None: 

return (E, v) 

else: 

return E 

  

def _echelon_classical(self): 

""" 

Return the echelon form of self. 

""" 

E = self.fetch('echelon_classical') 

if not E is None: 

return E 

E = self.__copy__() 

E._echelon_in_place_classical() 

self.cache('echelon_classical', E) 

return E 

  

def _echelon_in_place_classical(self): 

""" 

Transform self into echelon form and set the pivots of self. 

  

EXAMPLES:: 

  

sage: t = matrix(QQ, 3, 3, range(9)); t 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: E = t._echelon_in_place_classical(); t 

[ 1 0 -1] 

[ 0 1 2] 

[ 0 0 0] 

sage: a = matrix(QQ,2,[1..6]) 

sage: P = a._echelon_in_place_classical(); a 

[ 1 0 -1] 

[ 0 1 2] 

""" 

tm = verbose('generic in-place Gauss elimination on %s x %s matrix'%(self._nrows, self._ncols)) 

cdef Py_ssize_t start_row, c, r, nr, nc, i 

if self.fetch('in_echelon_form'): 

return self.fetch('pivots') 

  

self.check_mutability() 

cdef Matrix A 

  

nr = self._nrows 

nc = self._ncols 

A = self 

  

start_row = 0 

pivots = [] 

  

for c in range(nc): 

sig_check() 

for r in range(start_row, nr): 

if A.get_unsafe(r, c): 

pivots.append(c) 

a_inverse = ~A.get_unsafe(r,c) 

A.rescale_row(r, a_inverse, c) 

A.swap_rows(r, start_row) 

for i in range(nr): 

if i != start_row: 

if A.get_unsafe(i,c): 

minus_b = -A.get_unsafe(i, c) 

A.add_multiple_of_row(i, start_row, minus_b, c) 

start_row = start_row + 1 

break 

pivots = tuple(pivots) 

self.cache('pivots', pivots) 

self.cache('in_echelon_form', True) 

self.cache('echelon_form', self) 

return pivots 

  

def extended_echelon_form(self, subdivide=False, **kwds): 

r""" 

Returns the echelon form of ``self`` augmented with an identity matrix. 

  

INPUT: 

  

- ``subdivide`` - default: ``False`` - determines if the 

returned matrix is subdivided. See the description of the 

(output) below for details. 

- ``kwds`` - additional keywords that can be passed to 

the method that computes the echelon form. 

  

OUTPUT: 

  

If `A` is an `m\times n` matrix, add the `m` columns of an 

`m\times m` identity matrix to the right of ``self``. Then 

row-reduce this `m\times(n+m)` matrix. This matrix is returned 

as an immutable matrix. 

  

If ``subdivide`` is ``True`` then the returned matrix has a single 

division among the columns and a single division among the rows. 

The column subdivision has `n` columns to the left and `m` 

columns to the right. The row division separates the non-zero rows 

from the zero rows, when restricted to the first `n` columns. 

  

For a nonsingular matrix the final `m` columns of the extended 

echelon form are the inverse of ``self``. For a matrix of 

any size, the final `m` columns provide a matrix that transforms 

``self`` to echelon form when it multiplies ``self`` from the left. 

When the base ring is a field, the uniqueness of reduced row-echelon 

form implies that this transformation matrix can be taken as the 

coefficients giving a 

canonical set of linear combinations of the rows of ``self`` that 

yield reduced row-echelon form. 

  

When subdivided as described above, and again over a field, the 

parts of the subdivision in the upper-left corner and lower-right 

corner satisfy several interesting relationships with the row space, 

column space, left kernel and right kernel of ``self``. See the 

examples below. 

  

.. NOTE:: 

  

This method returns an echelon form. If the base ring 

is not a field, no atttempt is made to move to the fraction field. 

See an example below where the base ring is changed manually. 

  

EXAMPLES: 

  

The four relationships at the end of this example hold in general. :: 

  

sage: A = matrix(QQ, [[2, -1, 7, -1, 0, -3], 

....: [-1, 1, -5, 3, 4, 4], 

....: [2, -1, 7, 0, 2, -2], 

....: [2, 0, 4, 3, 6, 1], 

....: [2, -1, 7, 0, 2, -2]]) 

sage: E = A.extended_echelon_form(subdivide=True); E 

[ 1 0 2 0 0 -1| 0 -1 0 1 -1] 

[ 0 1 -3 0 -2 0| 0 -2 0 2 -3] 

[ 0 0 0 1 2 1| 0 2/3 0 -1/3 2/3] 

[-----------------------------+------------------------] 

[ 0 0 0 0 0 0| 1 2/3 0 -1/3 -1/3] 

[ 0 0 0 0 0 0| 0 0 1 0 -1] 

sage: J = E.matrix_from_columns(range(6,11)); J 

[ 0 -1 0 1 -1] 

[ 0 -2 0 2 -3] 

[ 0 2/3 0 -1/3 2/3] 

[ 1 2/3 0 -1/3 -1/3] 

[ 0 0 1 0 -1] 

sage: J*A == A.rref() 

True 

sage: C = E.subdivision(0,0); C 

[ 1 0 2 0 0 -1] 

[ 0 1 -3 0 -2 0] 

[ 0 0 0 1 2 1] 

sage: L = E.subdivision(1,1); L 

[ 1 2/3 0 -1/3 -1/3] 

[ 0 0 1 0 -1] 

sage: A.right_kernel() == C.right_kernel() 

True 

sage: A.row_space() == C.row_space() 

True 

sage: A.column_space() == L.right_kernel() 

True 

sage: A.left_kernel() == L.row_space() 

True 

  

For a nonsingular matrix, the right half of the extended 

echelon form is the inverse matrix. :: 

  

sage: B = matrix(QQ, [[1,3,4], [1,4,4], [0,-2,-1]]) 

sage: E = B.extended_echelon_form() 

sage: J = E.matrix_from_columns(range(3,6)); J 

[-4 5 4] 

[-1 1 0] 

[ 2 -2 -1] 

sage: J == B.inverse() 

True 

  

The result is in echelon form, so if the base ring is 

not a field, the leading entry of each row may not be 1. 

But you can easily change to the fraction field if necessary. :: 

  

sage: A = matrix(ZZ, [[16, 20, 4, 5, -4, 13, 5], 

....: [10, 13, 3, -3, 7, 11, 6], 

....: [-12, -15, -3, -3, 2, -10, -4], 

....: [10, 13, 3, 3, -1, 9, 4], 

....: [4, 5, 1, 8, -10, 1, -1]]) 

sage: E = A.extended_echelon_form(subdivide=True); E 

[ 2 0 -2 2 -9 -3 -4| 0 4 -3 -9 4] 

[ 0 1 1 2 0 1 1| 0 1 2 1 1] 

[ 0 0 0 3 -4 -1 -1| 0 3 1 -3 3] 

[--------------------+--------------] 

[ 0 0 0 0 0 0 0| 1 6 3 -6 5] 

[ 0 0 0 0 0 0 0| 0 7 2 -7 6] 

sage: J = E.matrix_from_columns(range(7,12)); J 

[ 0 4 -3 -9 4] 

[ 0 1 2 1 1] 

[ 0 3 1 -3 3] 

[ 1 6 3 -6 5] 

[ 0 7 2 -7 6] 

sage: J*A == A.echelon_form() 

True 

sage: B = A.change_ring(QQ) 

sage: B.extended_echelon_form(subdivide=True) 

[ 1 0 -1 0 -19/6 -7/6 -5/3| 0 0 -89/42 -5/2 1/7] 

[ 0 1 1 0 8/3 5/3 5/3| 0 0 34/21 2 -1/7] 

[ 0 0 0 1 -4/3 -1/3 -1/3| 0 0 1/21 0 1/7] 

[------------------------------------------------+----------------------------------] 

[ 0 0 0 0 0 0 0| 1 0 9/7 0 -1/7] 

[ 0 0 0 0 0 0 0| 0 1 2/7 -1 6/7] 

  

Subdivided, or not, the result is immutable, so make a 

copy if you want to make changes. :: 

  

sage: A = matrix(FiniteField(7), [[2,0,3], [5,5,3], [5,6,5]]) 

sage: E = A.extended_echelon_form() 

sage: E.is_mutable() 

False 

sage: F = A.extended_echelon_form(subdivide=True) 

sage: F 

[1 0 0|0 4 6] 

[0 1 0|4 2 2] 

[0 0 1|5 2 3] 

[-----+-----] 

sage: F.is_mutable() 

False 

sage: G = copy(F) 

sage: G.subdivide([],[]); G 

[1 0 0 0 4 6] 

[0 1 0 4 2 2] 

[0 0 1 5 2 3] 

  

If you want to determine exactly which algorithm is 

used to compute the echelon form, you can add additional 

keywords to pass on to the ``echelon_form()`` routine 

employed on the augmented matrix. Sending the flag 

``include_zero_rows`` is a bit silly, since the 

extended echelon form will never have any zero rows. :: 

  

sage: A = matrix(ZZ, [[1,2], [5,0], [5,9]]) 

sage: E = A.extended_echelon_form(algorithm='padic', include_zero_rows=False) 

sage: E 

[ 1 0 36 1 -8] 

[ 0 1 5 0 -1] 

[ 0 0 45 1 -10] 

  

TESTS: 

  

The ``subdivide`` keyword is checked. :: 

  

sage: A = matrix(QQ, 2, range(4)) 

sage: A.extended_echelon_form(subdivide='junk') 

Traceback (most recent call last): 

... 

TypeError: subdivide must be True or False, not junk 

  

AUTHOR: 

  

- Rob Beezer (2011-02-02) 

""" 

if not subdivide in [True, False]: 

raise TypeError("subdivide must be True or False, not %s" % subdivide) 

R = self.base_ring() 

ident = self.matrix_space(self.nrows(), self.nrows()).one() 

E = self.augment(ident) 

extended = E.echelon_form(**kwds) 

if subdivide: 

from copy import copy 

extended = copy(extended) 

# pivots of E are cached from echelon form computation 

rank = len([c for c in E.pivots() if c < self.ncols()]) 

extended.subdivide(rank, self.ncols()) 

extended.set_immutable() 

return extended 

  

def row_reduced_form(self, transformation=None): 

r""" 

This function computes a row reduced form of a matrix over a rational 

function field `k(x)`, where `k` is a field. 

  

A matrix `M` over `k(x)` is row reduced if the (row-wise) leading term 

matrix of `dM` has the same rank as `M`, where `d \in k[x]` is a minimal 

degree polynomial such that `dM` is in `k[x]`. The (row-wise) leading 

term matrix of a polynomial matrix `M_0` is matrix over `k` whose 

`(i,j)`'th entry is the `x^{d_i}` coefficient of `M_0[i,j]`, where `d_i` 

is the greatest degree among polynomials in the `i`'th row of `M_0`. 

  

INPUT: 

  

- ``transformation`` -- A boolean (default: ``False``). If this is set to 

``True``, the transformation matrix `U` will be returned as well: this 

is an invertible matrix over `k(x)` such that ``self`` equals `UW`, 

where `W` is the output matrix. 

  

OUTPUT: 

  

- `W` - a matrix over the same ring as `self` (i.e. either `k(x)` or 

`k[x]` for a field `k`) giving a row reduced form of ``self``. 

  

EXAMPLES: 

  

The routine expects matrices over the rational function field. One can 

also provide matrices over the ring of polynomials (whose quotient field 

is the rational function field). 

  

:: 

  

sage: R.<t> = GF(3)['t'] 

sage: K = FractionField(R) 

sage: M = matrix([[(t-1)^2/t],[(t-1)]]) 

sage: M.row_reduced_form() 

doctest:...: DeprecationWarning: Row reduced form will soon be supported only for matrices of polynomials. 

See http://trac.sagemath.org/21024 for details. 

[ 0] 

[(t + 2)/t] 

  

If ``self`` is an `n \times 1` matrix with at least one non-zero entry, 

`W` has a single non-zero entry and that entry is a scalar multiple of 

the greatest-common-divisor of the entries of ``self``. 

  

:: 

  

sage: M1 = matrix([[t*(t-1)*(t+1)],[t*(t-2)*(t+2)],[t]]) 

sage: output1 = M1.row_reduced_form() 

sage: output1 

[0] 

[0] 

[t] 

  

We check that the output is the same for a matrix `M` if its entries are 

rational functions instead of polynomials. We also check that the type of 

the output follows the documentation. See :trac:`9063` 

  

:: 

  

sage: M2 = M1.change_ring(K) 

sage: output2 = M2.row_reduced_form() 

sage: output1 == output2 

True 

sage: output1.base_ring() is R 

True 

sage: output2.base_ring() is K 

True 

  

The following is the first half of example 5 in [Hes2002]_ *except* that we 

have transposed ``self``; [Hes2002]_ uses column operations and we use row. 

  

:: 

  

sage: R.<t> = QQ['t'] 

sage: M = matrix([[t^3 - t,t^2 - 2],[0,t]]).transpose() 

sage: M.row_reduced_form(transformation=False) 

[ t -t^2] 

[t^2 - 2 t] 

  

The next example demonstrates what happens when ``self`` is a zero matrix. 

  

:: 

  

sage: R.<t> = GF(5)['t'] 

sage: K = FractionField(R) 

sage: M = matrix([[K(0),K(0)],[K(0),K(0)]]) 

sage: M.row_reduced_form() 

[0 0] 

[0 0] 

  

In the following example, ``self`` has more rows than columns. 

  

:: 

  

sage: R.<t> = QQ['t'] 

sage: M = matrix([[t,t,t],[0,0,t]]) 

sage: M.row_reduced_form() 

[ t t t] 

[-t -t 0] 

  

The next example shows that `M` must be a matrix with coefficients in 

`k(t)` or in `k[t]` for some field `k`. 

  

:: 

  

sage: M = matrix([[1,0],[1,1]]) 

sage: M.row_reduced_form() 

Traceback (most recent call last): 

... 

TypeError: the coefficients of M must lie in a univariate polynomial ring over a field 

  

sage: PZ.<y> = ZZ[] 

sage: M = matrix([[y,0],[1,y]]) 

sage: M.row_reduced_form() 

Traceback (most recent call last): 

... 

TypeError: the coefficients of M must lie in a univariate polynomial ring over a field 

  

The last example shows the usage of the transformation parameter. 

  

:: 

  

sage: Fq.<a> = GF(2^3) 

sage: Fx.<x> = Fq[] 

sage: A = matrix(Fx,[[x^2+a,x^4+a],[x^3,a*x^4]]) 

sage: W,U = A.row_reduced_form(transformation=True); 

sage: W,U 

( 

[ x^2 + a x^4 + a] [1 0] 

[x^3 + a*x^2 + a^2 a^2], [a 1] 

) 

sage: U*W == A 

True 

sage: U.is_invertible() 

True 

  

NOTES: 

  

- For consistency with LLL and other algorithms in Sage, we have opted 

for row operations; however, some references e.g. [Hes2002]_ transpose and use 

column operations. 

  

REFERENCES: 

  

- [Hes2002]_ 

- [Kal1980]_ 

  

""" 

from sage.misc.superseded import deprecation 

# When deprecation period runs out, this method should simply be removed from this class. 

# matrix_polynomial_dense already has the replacement row_reduced_form method. 

# The function matrix_misc.row_reduced_form should then probably just be removed. 

deprecation(21024, "Row reduced form will soon be supported only for matrices of univariate polynomials.") 

  

from sage.matrix.matrix_misc import row_reduced_form 

return row_reduced_form(self, transformation) 

  

########################################################################## 

# Functions for symmetries of a matrix under row and column permutations # 

########################################################################## 

def as_bipartite_graph(self): 

r""" 

Construct a bipartite graph ``B`` representing 

the matrix uniquely. 

  

Vertices are labeled 1 to ``nrows`` 

on the left and ``nrows`` + 1 to ``nrows`` + ``ncols`` on 

the right, representing rows and columns correspondingly. 

Each row is connected to each column with an edge 

weighted by the value of the corresponding matrix entry. 

  

This graph is a helper for calculating automorphisms of 

a matrix under row and column permutations. See 

:meth:`automorphisms_of_rows_and_columns`. 

  

OUTPUT: 

  

- A bipartite graph. 

  

EXAMPLES:: 

  

sage: M = matrix(QQ, [[1/3, 7], [6, 1/4], [8, -5]]) 

sage: M 

[1/3 7] 

[ 6 1/4] 

[ 8 -5] 

  

sage: B = M.as_bipartite_graph() 

sage: B 

Bipartite graph on 5 vertices 

sage: B.edges() 

[(1, 4, 1/3), (1, 5, 7), (2, 4, 6), (2, 5, 1/4), (3, 4, 8), (3, 5, -5)] 

sage: len(B.left) == M.nrows() 

True 

sage: len(B.right) == M.ncols() 

True 

""" 

from sage.graphs.bipartite_graph import BipartiteGraph 

nrows = self.nrows() 

ncols = self.ncols() 

B = BipartiteGraph() 

B.add_vertices(range(1, nrows + 1), left=True) 

B.add_vertices(range(nrows + 1, nrows + ncols + 1), right=True) 

for i in range(nrows): 

for j in range(ncols): 

B.add_edge(i + 1, nrows + 1 + j, self[i][j]) 

return B 

  

def automorphisms_of_rows_and_columns(self): 

r""" 

Return the automorphisms of ``self`` under 

permutations of rows and columns as a list of 

pairs of ``PermutationGroupElement`` objects. 

  

EXAMPLES:: 

  

sage: M = matrix(ZZ,[[1,0],[1,0],[0,1]]) 

sage: M 

[1 0] 

[1 0] 

[0 1] 

sage: A = M.automorphisms_of_rows_and_columns() 

sage: A 

[((), ()), ((1,2), ())] 

sage: M = matrix(ZZ,[[1,1,1,1],[1,1,1,1]]) 

sage: A = M.automorphisms_of_rows_and_columns() 

sage: len(A) 

48 

  

One can now apply these automorphisms to ``M`` to show 

that it leaves it invariant:: 

  

sage: all(M.with_permuted_rows_and_columns(*i) == M for i in A) 

True 

""" 

from sage.groups.perm_gps.permgroup_element import \ 

PermutationGroupElement 

B = self.as_bipartite_graph() 

nrows = self.nrows() 

A = B.automorphism_group(edge_labels = True) 

permutations = [] 

for p in A: 

p = p.domain() 

# Convert to elements of Sym(self) from S_n 

if p[0] <= nrows: 

permutations.append( 

(PermutationGroupElement(p[:nrows]), 

PermutationGroupElement([elt - nrows for elt in p[nrows:]]) 

)) 

return permutations 

  

def permutation_normal_form(self, check=False): 

r""" 

Take the set of matrices that are ``self`` 

permuted by any row and column permutation, 

and return the maximal one of the set where 

matrices are ordered lexicographically 

going along each row. 

  

INPUT: 

  

- ``check`` -- (default: ``False``) If ``True`` return a tuple of 

the maximal matrix and the permutations taking ``self`` 

to the maximal matrix. 

If ``False``, return only the maximal matrix. 

  

OUTPUT: 

  

The maximal matrix. 

  

EXAMPLES:: 

  

sage: M = matrix(ZZ, [[0, 0, 1], [1, 0, 2], [0, 0, 0]]) 

sage: M 

[0 0 1] 

[1 0 2] 

[0 0 0] 

  

sage: M.permutation_normal_form() 

[2 1 0] 

[1 0 0] 

[0 0 0] 

  

sage: M = matrix(ZZ, [[-1, 3], [-1, 5], [2, 4]]) 

sage: M 

[-1 3] 

[-1 5] 

[ 2 4] 

  

sage: M.permutation_normal_form(check=True) 

( 

[ 5 -1] 

[ 4 2] 

[ 3 -1], 

((1,2,3), (1,2)) 

) 

  

TESTS:: 

  

sage: M = matrix(ZZ, [[3, 4, 5], [3, 4, 5], [3, 5, 4], [2, 0,1]]) 

sage: M.permutation_normal_form() 

[5 4 3] 

[5 4 3] 

[4 5 3] 

[1 0 2] 

""" 

nrows = self.nrows() 

ncols = self.ncols() 

  

# A helper 

def new_sorted_matrix(m): 

return self.new_matrix( 

ncols, nrows, 

sorted(m.columns(), reverse=True)).transpose() 

  

# Let us sort each row: 

sorted_rows = [sorted([self[i][j] for j in range(ncols)], reverse=True) 

for i in range(nrows)] 

# and find the maximal one: 

first_row = max(sorted_rows) 

first_rows = [j for j in range(nrows) if sorted_rows[j] == first_row] 

# We construct an array S, which will record the subsymmetries of the 

# columns, i.e. S records the automorphisms with respect to the column 

# swappings of the upper block already constructed. For example, if 

# allowed, and so on. S is in decreasing order and takes values between 

# S:=[a, a, ..., a (i-th), a-1, a-1, ...] then any swap between 1 and i is 

# me + nc and me + 1 such that no entry is present already in the matrix. 

S = [first_row[0] + ncols] + [None]*(ncols-1) 

for j in range(1, ncols): 

S[j] = S[j - 1] if first_row[j] == first_row[j - 1] else S[j - 1] - 1 

# If we want to sort the i-th row with respect to a symmetry determined 

# by S, then we will just sort the augmented row [[S[j], PM[i, j]] : 

# j in [1 .. nc]], S having lexicographic priority. 

  

# MS is a list of non-isomorphic matrices where one of the maximal rows 

# has been replaced by S 

MS = [] 

aM = [] 

if self.is_immutable(): 

X = copy(self) 

else: 

X = self 

for i in first_rows: 

N = new_sorted_matrix(X.with_swapped_rows(0, i)) 

aN = copy(N) 

aN.set_row(0, S) 

if not any(aN.is_permutation_of(j) for j in aM): 

MS.append(N) 

aM.append(aN) 

# We construct line l: 

for l in range(1, nrows - 1): 

if not S == list(xrange(first_row[0] + ncols, first_row[0], -1)): 

# Sort each row with respect to S for the first matrix in X = MS 

X = copy(MS) 

SM = [sorted([(S[j], X[0][k][j]) for j in range(ncols)], reverse=True) 

for k in range(l, nrows)] 

SM = [[k[1] for k in s] for s in SM] 

  

# and pick the maximal row 

b = max(SM) 

# Find all rows equal to the maximal (potential new cases) 

m = [[j for j in range(nrows - l) if SM[j] == b]] 

w = 0 # keeps track of how many entries we have removed from MS 

# Let us find the maximal row in each of the entries in X = MS 

for i in range(1, len(X)): 

SN = [sorted([(S[j], X[i][k][j]) for j in range(ncols)], reverse=True) 

for k in range(l, nrows)] 

SN = [[k[1] for k in s] for s in SN] 

# Maximal row in this entry of X = MS 

nb = max(SN) 

# Number of occurrences. 

n = [j for j in range(nrows - l) if SN[j] == nb] 

# Now compare to our previous max 

if b < nb: 

# Bigger so save line 

b = nb 

m = [n] 

# and delete all previous attempts 

u = i - w 

del MS[0:u] 

w += u 

elif b == nb: 

# Same, so save symmetry 

m.append(n) 

else: 

# Smaller, so forget about it! 

MS.pop(i - w) 

w += 1 

# Update symmetries 

test = [(S[i], b[i]) for i in range(ncols)] 

for j in range(1, ncols): 

S[j] = S[j - 1] if (test[j] == test[j - 1]) else S[j - 1] - 1 

# For each case we check the isomorphism as previously, if 

# test fails we add a new non-isomorphic case to MS. We 

# pick our choice of maximal line l and sort the columns of 

# the matrix (this preserves symmetry automatically). 

n = len(MS) 

for i in range(n): 

MS[i] = new_sorted_matrix(MS[i].with_swapped_rows(l, m[i][0] + l)) 

if len(m[i]) > 1: 

aX = MS[i].submatrix(l, 0, nrows - l, ncols) 

aX.set_row(0, S) 

aX = [aX] 

for j in m[i][1:]: 

N = new_sorted_matrix(MS[i].with_swapped_rows(l, j + 1)) 

aN = N.submatrix(l, 0, nrows - l, ncols) 

aN.set_row(0, S) 

if not any(aN.is_permutation_of(k) for k in aX): 

MS.append(N) 

aX.append(aN) 

else: 

MS = [self.new_matrix(nrows, ncols, sorted(s.rows(), reverse=True)) for s in MS] 

break 

MS_max = max(MS) 

if check: 

return MS_max, self.is_permutation_of(MS_max, True)[1] 

else: 

return MS_max 

  

def is_permutation_of(self, N, check=False): 

r""" 

Return ``True`` if there exists a permutation of rows and 

columns sending ``self`` to ``N`` and ``False`` otherwise. 

  

INPUT: 

  

- ``N`` -- a matrix. 

  

- ``check`` -- boolean (default: ``False``). If ``False`` 

return Boolean indicating whether there exists a permutation of 

rows and columns sending ``self`` to ``N`` and False otherwise. 

If ``True`` return a tuple of a Boolean and a permutation mapping 

``self`` to ``N`` if such a permutation exists, and 

(``False``, ``None``) if it does not. 

  

OUTPUT: 

  

A Boolean or a tuple of a Boolean and a permutation. 

  

EXAMPLES:: 

  

sage: M = matrix(ZZ,[[1,2,3],[3,5,3],[2,6,4]]) 

sage: M 

[1 2 3] 

[3 5 3] 

[2 6 4] 

sage: N = matrix(ZZ,[[1,2,3],[2,6,4],[3,5,3]]) 

sage: N 

[1 2 3] 

[2 6 4] 

[3 5 3] 

sage: M.is_permutation_of(N) 

True 

  

Some examples that are not permutations of each other:: 

  

sage: N = matrix(ZZ,[[1,2,3],[4,5,6],[7,8,9]]) 

sage: N 

[1 2 3] 

[4 5 6] 

[7 8 9] 

sage: M.is_permutation_of(N) 

False 

sage: N = matrix(ZZ,[[1,2],[3,4]]) 

sage: N 

[1 2] 

[3 4] 

sage: M.is_permutation_of(N) 

False 

  

And for when ``check`` is True:: 

  

sage: N = matrix(ZZ,[[3,5,3],[2,6,4],[1,2,3]]) 

sage: N 

[3 5 3] 

[2 6 4] 

[1 2 3] 

sage: r = M.is_permutation_of(N, check=True) 

sage: r 

(True, ((1,2,3), ())) 

sage: p = r[1] 

sage: M.with_permuted_rows_and_columns(*p) == N 

True 

""" 

ncols = self.ncols() 

nrows = self.nrows() 

if N.ncols() != ncols or N.nrows() != nrows: 

if check: 

return (False, None) 

else: 

return False 

M_B = self.as_bipartite_graph() 

N_B = N.as_bipartite_graph() 

if check: 

truth, perm = N_B.is_isomorphic(M_B, certificate=True, edge_labels=True) 

from sage.groups.perm_gps.permgroup_element import PermutationGroupElement 

if perm: 

s = sorted(perm.items(), key=lambda x:x[0]) 

row_perms = [value for k, value in s if k <= nrows] 

col_perms = [value - nrows for k, value in s if k > nrows] 

perm = (PermutationGroupElement(row_perms), PermutationGroupElement(col_perms)) 

return truth, perm 

else: 

return N_B.is_isomorphic(M_B, certificate=False, edge_labels=True) 

  

##################################################################################### 

# Windowed Strassen Matrix Multiplication and Echelon 

# Precise algorithms invented and implemented by David Harvey and Robert Bradshaw 

# at William Stein's MSRI 2006 Summer Workshop on Modular Forms. 

##################################################################################### 

def _multiply_strassen(self, Matrix right, int cutoff=0): 

""" 

Multiply self by the matrix right using a Strassen-based 

asymptotically fast arithmetic algorithm. 

  

ALGORITHM: Custom algorithm for arbitrary size matrices designed by 

David Harvey and Robert Bradshaw, based on Strassen's algorithm. 

  

INPUT: 

  

  

- ``cutoff`` - integer (default: 0 - let class 

decide). 

  

  

EXAMPLES:: 

  

sage: a = matrix(ZZ,4,4,range(16)) 

sage: a._multiply_strassen(a,2) 

[ 56 62 68 74] 

[152 174 196 218] 

[248 286 324 362] 

[344 398 452 506] 

""" 

if self._ncols != right._nrows: 

raise ArithmeticError("Number of columns of self must equal number of rows of right.") 

if not self._base_ring is right.base_ring(): 

raise TypeError("Base rings must be the same.") 

  

if cutoff == 0: 

cutoff = self._strassen_default_cutoff(right) 

  

if cutoff <= 0: 

raise ValueError("cutoff must be at least 1") 

  

output = self.new_matrix(self._nrows, right._ncols) 

# The following used to be a little faster, but meanwhile 

# the previous line is faster. 

#if self.is_sparse(): 

# output = self.matrix_space(self._nrows, right._ncols, sparse = True)(0) 

#else: 

# output = self.matrix_space(self._nrows, right._ncols, sparse = False).zero_matrix().__copy__() 

  

self_window = self.matrix_window() 

right_window = right.matrix_window() 

output_window = output.matrix_window() 

  

  

from . import strassen 

strassen.strassen_window_multiply(output_window, self_window, right_window, cutoff) 

return output 

  

def _echelon_strassen(self, int cutoff=0): 

""" 

In place Strassen echelon of self, and sets the pivots. 

  

ALGORITHM: Custom algorithm for arbitrary size matrices designed by 

David Harvey and Robert Bradshaw, based on Strassen's algorithm. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, 4, range(16)) 

sage: A._echelon_strassen(2) 

sage: A 

[ 1 0 -1 -2] 

[ 0 1 2 3] 

[ 0 0 0 0] 

[ 0 0 0 0] 

""" 

tm = verbose('strassen echelon of %s x %s matrix'%(self._nrows, self._ncols)) 

  

self.check_mutability() 

  

if not self._base_ring.is_field(): 

raise ValueError("Echelon form not defined over this base ring.") 

  

if cutoff == 0: 

cutoff = self._strassen_default_echelon_cutoff() 

  

if cutoff < 1: 

raise ValueError("cutoff must be at least 1") 

  

if self._nrows < cutoff or self._ncols < cutoff: 

self._echelon_in_place_classical() 

return 

  

from . import strassen 

pivots = strassen.strassen_echelon(self.matrix_window(), cutoff) 

self.cache('pivots', pivots) 

verbose('done with strassen', tm) 

  

cpdef matrix_window(self, Py_ssize_t row=0, Py_ssize_t col=0, 

Py_ssize_t nrows=-1, Py_ssize_t ncols=-1, 

bint check=1): 

""" 

Return the requested matrix window. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, 3, 3, range(9)) 

sage: A.matrix_window(1,1, 2, 1) 

Matrix window of size 2 x 1 at (1,1): 

[0 1 2] 

[3 4 5] 

[6 7 8] 

  

We test the optional check flag. 

  

:: 

  

sage: matrix([1]).matrix_window(0,1,1,1, check=False) 

Matrix window of size 1 x 1 at (0,1): 

[1] 

sage: matrix([1]).matrix_window(0,1,1,1) 

Traceback (most recent call last): 

... 

IndexError: matrix window index out of range 

  

Another test of bounds checking:: 

  

sage: matrix([1]).matrix_window(1,1,1,1) 

Traceback (most recent call last): 

... 

IndexError: matrix window index out of range 

""" 

from . import matrix_window 

if nrows == -1: 

nrows = self._nrows - row 

if ncols == -1: 

ncols = self._ncols - col 

if check and (row < 0 or col < 0 or row + nrows > self._nrows or \ 

col + ncols > self._ncols): 

raise IndexError("matrix window index out of range") 

return matrix_window.MatrixWindow(self, row, col, nrows, ncols) 

  

def set_block(self, row, col, block): 

""" 

Sets the sub-matrix of self, with upper left corner given by row, 

col to block. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, 3, 3, range(9))/2 

sage: B = matrix(ZZ, 2, 1, [100,200]) 

sage: A.set_block(0, 1, B) 

sage: A 

[ 0 100 1] 

[3/2 200 5/2] 

[ 3 7/2 4] 

  

We test that an exception is raised when the block is out of 

bounds:: 

  

sage: matrix([1]).set_block(0,1,matrix([1])) 

Traceback (most recent call last): 

... 

IndexError: matrix window index out of range 

""" 

self.check_mutability() 

if block.base_ring() is not self.base_ring(): 

block = block.change_ring(self.base_ring()) 

window = self.matrix_window(row, col, block.nrows(), block.ncols(), check=True) 

window.set(block.matrix_window()) 

  

def subdivide(self, row_lines=None, col_lines=None): 

""" 

Divides self into logical submatrices which can then be queried and 

extracted. If a subdivision already exists, this method forgets the 

previous subdivision and flushes the cache. 

  

INPUT: 

  

  

- ``row_lines`` - None, an integer, or a list of 

integers (lines at which self must be split). 

  

- ``col_lines`` - None, an integer, or a list of 

integers (columns at which self must be split). 

  

  

OUTPUT: changes self 

  

.. NOTE:: 

  

One may also pass a tuple into the first argument which 

will be interpreted as (row_lines, col_lines) 

  

EXAMPLES:: 

  

sage: M = matrix(5, 5, prime_range(100)) 

sage: M.subdivide(2,3); M 

[ 2 3 5| 7 11] 

[13 17 19|23 29] 

[--------+-----] 

[31 37 41|43 47] 

[53 59 61|67 71] 

[73 79 83|89 97] 

sage: M.subdivision(0,0) 

[ 2 3 5] 

[13 17 19] 

sage: M.subdivision(1,0) 

[31 37 41] 

[53 59 61] 

[73 79 83] 

sage: M.subdivision_entry(1,0,0,0) 

31 

sage: M.subdivisions() 

([2], [3]) 

sage: M.subdivide(None, [1,3]); M 

[ 2| 3 5| 7 11] 

[13|17 19|23 29] 

[31|37 41|43 47] 

[53|59 61|67 71] 

[73|79 83|89 97] 

  

Degenerate cases work too:: 

  

sage: M.subdivide([2,5], [0,1,3]); M 

[| 2| 3 5| 7 11] 

[|13|17 19|23 29] 

[+--+-----+-----] 

[|31|37 41|43 47] 

[|53|59 61|67 71] 

[|73|79 83|89 97] 

[+--+-----+-----] 

sage: M.subdivision(0,0) 

[] 

sage: M.subdivision(0,1) 

[ 2] 

[13] 

sage: M.subdivide([2,2,3], [0,0,1,1]); M 

[|| 2|| 3 5 7 11] 

[||13||17 19 23 29] 

[++--++-----------] 

[++--++-----------] 

[||31||37 41 43 47] 

[++--++-----------] 

[||53||59 61 67 71] 

[||73||79 83 89 97] 

sage: M.subdivision(0,0) 

[] 

sage: M.subdivision(2,4) 

[37 41 43 47] 

  

Indices do not need to be in the right order (:trac:`14064`):: 

  

sage: M.subdivide([4, 2], [3, 1]); M 

[ 2| 3 5| 7 11] 

[13|17 19|23 29] 

[--+-----+-----] 

[31|37 41|43 47] 

[53|59 61|67 71] 

[--+-----+-----] 

[73|79 83|89 97] 

  

  

AUTHORS: 

  

- Robert Bradshaw (2007-06-14) 

""" 

  

self.check_mutability() 

if col_lines is None and row_lines is not None and isinstance(row_lines, tuple): 

tmp = row_lines 

row_lines, col_lines = tmp 

if row_lines is None: 

row_lines = [] 

elif not isinstance(row_lines, list): 

row_lines = [row_lines] 

if col_lines is None: 

col_lines = [] 

elif not isinstance(col_lines, list): 

col_lines = [col_lines] 

l_row = sorted(row_lines) 

l_col = sorted(col_lines) 

l_row = [0] + [int(ZZ(x)) for x in l_row] + [self._nrows] 

l_col = [0] + [int(ZZ(x)) for x in l_col] + [self._ncols] 

if self._subdivisions is not None: 

self.clear_cache() 

self._subdivisions = (l_row, l_col) 

  

def subdivision(self, i, j): 

""" 

Returns an immutable copy of the (i,j)th submatrix of self, 

according to a previously set subdivision. 

  

Before a subdivision is set, the only valid arguments are (0,0) 

which returns self. 

  

EXAMPLES:: 

  

sage: M = matrix(3, 4, range(12)) 

sage: M.subdivide(1,2); M 

[ 0 1| 2 3] 

[-----+-----] 

[ 4 5| 6 7] 

[ 8 9|10 11] 

sage: M.subdivision(0,0) 

[0 1] 

sage: M.subdivision(0,1) 

[2 3] 

sage: M.subdivision(1,0) 

[4 5] 

[8 9] 

  

It handles size-zero subdivisions as well. 

  

:: 

  

sage: M = matrix(3, 4, range(12)) 

sage: M.subdivide([0],[0,2,2,4]); M 

[+-----++-----+] 

[| 0 1|| 2 3|] 

[| 4 5|| 6 7|] 

[| 8 9||10 11|] 

sage: M.subdivision(0,0) 

[] 

sage: M.subdivision(1,1) 

[0 1] 

[4 5] 

[8 9] 

sage: M.subdivision(1,2) 

[] 

sage: M.subdivision(1,0) 

[] 

sage: M.subdivision(0,1) 

[] 

""" 

if self._subdivisions is None: 

self._subdivisions = ([0, self._nrows], [0, self._ncols]) 

key = "subdivision %s %s"%(i,j) 

sd = self.fetch(key) 

if sd is None: 

sd = self[self._subdivisions[0][i]:self._subdivisions[0][i+1], 

self._subdivisions[1][j]:self._subdivisions[1][j+1]] 

sd.set_immutable() 

self.cache(key, sd) 

return sd 

  

def subdivision_entry(self, i, j, x, y): 

""" 

Returns the x,y entry of the i,j submatrix of self. 

  

EXAMPLES:: 

  

sage: M = matrix(5, 5, range(25)) 

sage: M.subdivide(3,3); M 

[ 0 1 2| 3 4] 

[ 5 6 7| 8 9] 

[10 11 12|13 14] 

[--------+-----] 

[15 16 17|18 19] 

[20 21 22|23 24] 

sage: M.subdivision_entry(0,0,1,2) 

7 

sage: M.subdivision(0,0)[1,2] 

7 

sage: M.subdivision_entry(0,1,0,0) 

3 

sage: M.subdivision_entry(1,0,0,0) 

15 

sage: M.subdivision_entry(1,1,1,1) 

24 

  

Even though this entry exists in the matrix, the index is invalid 

for the submatrix. 

  

:: 

  

sage: M.subdivision_entry(0,0,4,0) 

Traceback (most recent call last): 

... 

IndexError: Submatrix 0,0 has no entry 4,0 

""" 

if self._subdivisions is None: 

if not i and not j: 

return self[x,y] 

else: 

raise IndexError("No such submatrix %s, %s"%(i,j)) 

if x >= self._subdivisions[0][i+1]-self._subdivisions[0][i] or \ 

y >= self._subdivisions[1][j+1]-self._subdivisions[1][j]: 

raise IndexError("Submatrix %s,%s has no entry %s,%s"%(i,j, x, y)) 

return self[self._subdivisions[0][i] + x , self._subdivisions[1][j] + y] 

  

def _subdivide_on_augment(self, left, right): 

r""" 

Helper method to manage subdivisions when augmenting a matrix. 

  

INPUT: 

  

- ``left``, ``right`` - two matrices, such that if ``left`` is 

augmented by placing ``right`` on the right side of ``left``, 

then the result is ``self``. It is the responsibility of the 

calling routine to ensure this condition holds. 

  

OUTPUT: 

  

``None``. A new subdivision is created between ``left`` and 

``right`` for ``self``. If possible, row subdivisions are 

preserved in ``self``, but if the two sets of row subdivisions 

are incompatible, they are removed. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, 3, 4, range(12)) 

sage: B = matrix(QQ, 3, 6, range(18)) 

sage: C = A.augment(B) 

sage: C._subdivide_on_augment(A, B) 

sage: C 

[ 0 1 2 3| 0 1 2 3 4 5] 

[ 4 5 6 7| 6 7 8 9 10 11] 

[ 8 9 10 11|12 13 14 15 16 17] 

  

More descriptive, but indirect, doctests are at 

:meth:`sage.matrix.matrix1.Matrix.augment`. 

""" 

left_rows, left_cols = left.subdivisions() 

right_rows, right_cols = right.subdivisions() 

if left_rows == right_rows: 

self_rows = left_rows 

else: 

self_rows = None 

nc = left.ncols() 

self_cols = left_cols + [nc] 

for col in right_cols: 

self_cols.append(col+nc) 

self.subdivide(self_rows, self_cols) 

return None 

  

def _subdivide_on_stack(self, top, bottom): 

r""" 

Helper method to manage subdivisions when stacking a matrix. 

  

INPUT: 

  

- ``top``, ``bottom`` - two matrices, such that if ``top`` is 

stacked by placing ``top`` above ``bottom``, then the result 

is ``self``. It is the responsibility of the calling routine 

to ensure this condition holds. 

  

OUTPUT: 

  

``None``. A new subdivision is created between ``top`` and 

``bottom`` for ``self``. If possible, column subdivisions are 

preserved in ``self``, but if the two sets of column subdivisions 

are incompatible, they are removed. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, 3, 2, range(6)) 

sage: B = matrix(QQ, 4, 2, range(8)) 

sage: C = A.stack(B) 

sage: C._subdivide_on_stack(A, B) 

sage: C 

[0 1] 

[2 3] 

[4 5] 

[---] 

[0 1] 

[2 3] 

[4 5] 

[6 7] 

  

More descriptive, but indirect, doctests are at 

:meth:`sage.matrix.matrix1.Matrix.augment`. 

""" 

top_rows, top_cols = top.subdivisions() 

bottom_rows, bottom_cols = bottom.subdivisions() 

if top_cols == bottom_cols: 

self_cols = top_cols 

else: 

self_cols = None 

nr = top.nrows() 

self_rows = top_rows + [nr] 

for row in bottom_rows: 

self_rows.append(row+nr) 

self.subdivide(self_rows, self_cols) 

return None 

  

def subdivisions(self): 

""" 

Returns the current subdivision of self. 

  

EXAMPLES:: 

  

sage: M = matrix(5, 5, range(25)) 

sage: M.subdivisions() 

([], []) 

sage: M.subdivide(2,3) 

sage: M.subdivisions() 

([2], [3]) 

sage: N = M.parent()(1) 

sage: N.subdivide(M.subdivisions()); N 

[1 0 0|0 0] 

[0 1 0|0 0] 

[-----+---] 

[0 0 1|0 0] 

[0 0 0|1 0] 

[0 0 0|0 1] 

""" 

if self._subdivisions is None: 

return ([], []) 

else: 

return (self._subdivisions[0][1:-1], self._subdivisions[1][1:-1]) 

  

# 'get_subdivisions' is kept for backwards compatibility: see #4983. 

get_subdivisions = subdivisions 

  

def tensor_product(self, A, subdivide=True): 

r""" 

Returns the tensor product of two matrices. 

  

INPUT: 

  

- ``A`` - a matrix 

- ``subdivide`` - default: True - whether or not to return 

natural subdivisions with the matrix 

  

OUTPUT: 

  

Replace each element of ``self`` by a copy of ``A``, but first 

create a scalar multiple of ``A`` by the element it replaces. 

So if ``self`` is an `m\times n` matrix and ``A`` is a 

`p\times q` matrix, then the tensor product is an `mp\times nq` 

matrix. By default, the matrix will be subdivided into 

submatrices of size `p\times q`. 

  

EXAMPLES:: 

  

sage: M1=Matrix(QQ,[[-1,0],[-1/2,-1]]) 

sage: M2=Matrix(ZZ,[[1,-1,2],[-2,4,8]]) 

sage: M1.tensor_product(M2) 

[ -1 1 -2| 0 0 0] 

[ 2 -4 -8| 0 0 0] 

[--------------+--------------] 

[-1/2 1/2 -1| -1 1 -2] 

[ 1 -2 -4| 2 -4 -8] 

sage: M2.tensor_product(M1) 

[ -1 0| 1 0| -2 0] 

[-1/2 -1| 1/2 1| -1 -2] 

[---------+---------+---------] 

[ 2 0| -4 0| -8 0] 

[ 1 2| -2 -4| -4 -8] 

  

Subdivisions can be optionally suppressed. :: 

  

sage: M1.tensor_product(M2, subdivide=False) 

[ -1 1 -2 0 0 0] 

[ 2 -4 -8 0 0 0] 

[-1/2 1/2 -1 -1 1 -2] 

[ 1 -2 -4 2 -4 -8] 

  

Different base rings are handled sensibly. :: 

  

sage: A = matrix(ZZ, 2, 3, range(6)) 

sage: B = matrix(FiniteField(23), 3, 4, range(12)) 

sage: C = matrix(FiniteField(29), 4, 5, range(20)) 

sage: D = A.tensor_product(B) 

sage: D.parent() 

Full MatrixSpace of 6 by 12 dense matrices over Finite Field of size 23 

sage: E = C.tensor_product(B) 

Traceback (most recent call last): 

... 

TypeError: unsupported operand parent(s) for *: 'Finite Field of size 29' and 'Full MatrixSpace of 3 by 4 dense matrices over Finite Field of size 23' 

  

The input is checked to be sure it is a matrix. :: 

  

sage: A = matrix(QQ, 2, 2, range(4)) 

sage: A.tensor_product('junk') 

Traceback (most recent call last): 

... 

TypeError: tensor product requires a second matrix, not junk 

  

TESTS: 

  

Check that `m \times 0` and `0 \times m` matrices work 

(:trac:`22769`):: 

  

sage: m1 = matrix(QQ, 1, 0, []) 

sage: m2 = matrix(QQ, 2, 2, [1, 2, 3, 4]) 

sage: m1.tensor_product(m2).dimensions() 

(2, 0) 

sage: m2.tensor_product(m1).dimensions() 

(2, 0) 

sage: m3 = matrix(QQ, 0, 3, []) 

sage: m3.tensor_product(m2).dimensions() 

(0, 6) 

sage: m2.tensor_product(m3).dimensions() 

(0, 6) 

  

sage: m1 = MatrixSpace(GF(5), 3, 2).an_element() 

sage: m2 = MatrixSpace(GF(5), 0, 4).an_element() 

sage: m1.tensor_product(m2).parent() 

Full MatrixSpace of 0 by 8 dense matrices over Finite Field of size 5 

""" 

if not isinstance(A, Matrix): 

raise TypeError('tensor product requires a second matrix, not {0}'.format(A)) 

from sage.matrix.constructor import block_matrix 

# Special case when one of the matrices is 0 \times m or m \times 0 

if self.nrows() == 0 or self.ncols() == 0 or A.nrows() == 0 or A.ncols() == 0: 

return self.matrix_space(self.nrows()*A.nrows(), 

self.ncols()*A.ncols()).zero_matrix().__copy__() 

return block_matrix(self.nrows(), self.ncols(), 

[x * A for x in self.list()], subdivide=subdivide) 

  

def randomize(self, density=1, nonzero=False, *args, **kwds): 

""" 

Replace a proportion of the entries of a matrix by random elements, 

leaving the remaining entries unchanged. 

  

.. NOTE:: 

  

The locations of the entries of the matrix to change are 

determined randomly, with the total number of locations 

determined by the ``density`` keyword. These locations 

are not guaranteed to be distinct. So it is possible 

that the same position can be chosen multiple times, 

especially for a very small matrix. The exception is 

when ``density = 1``, in which case every entry of the 

matrix will be changed. 

  

INPUT: 

  

- ``density`` - ``float`` (default: ``1``); upper bound for the 

proportion of entries that are changed 

- ``nonzero`` - Bool (default: ``False``); if ``True``, then new 

entries will be nonzero 

- ``*args, **kwds`` - Remaining parameters may be passed to the 

``random_element`` function of the base ring 

  

EXAMPLES: 

  

We construct the zero matrix over a polynomial ring. 

  

:: 

  

sage: a = matrix(QQ['x'], 3); a 

[0 0 0] 

[0 0 0] 

[0 0 0] 

  

We then randomize roughly half the entries:: 

  

sage: a.randomize(0.5) 

sage: a 

[ 1/2*x^2 - x - 12 1/2*x^2 - 1/95*x - 1/2 0] 

[-5/2*x^2 + 2/3*x - 1/4 0 0] 

[ -x^2 + 2/3*x 0 0] 

  

Now we randomize all the entries of the resulting matrix:: 

  

sage: a.randomize() 

sage: a 

[ 1/3*x^2 - x + 1 -x^2 + 1 x^2 - x] 

[ -1/14*x^2 - x - 1/4 -4*x - 1/5 -1/4*x^2 - 1/2*x + 4] 

[ 1/9*x^2 + 5/2*x - 3 -x^2 + 3/2*x + 1 -2/7*x^2 - x - 1/2] 

  

We create the zero matrix over the integers:: 

  

sage: a = matrix(ZZ, 2); a 

[0 0] 

[0 0] 

  

Then we randomize it; the ``x`` and ``y`` keywords, which determine the 

size of the random elements, are passed on to the ``random_element`` 

method for ``ZZ``. 

  

:: 

  

sage: a.randomize(x=-2^64, y=2^64) 

sage: a 

[-12401200298100116246 1709403521783430739] 

[ -4417091203680573707 17094769731745295000] 

""" 

randint = current_randstate().python_random().randint 

  

density = float(density) 

if density <= 0: 

return 

if density > 1: 

density = 1 

  

self.check_mutability() 

self.clear_cache() 

  

R = self.base_ring() 

  

cdef Py_ssize_t i, j, num 

  

if nonzero: 

if density >= 1: 

for i from 0 <= i < self._nrows: 

for j from 0 <= j < self._ncols: 

self.set_unsafe(i, j, R._random_nonzero_element(*args,\ 

**kwds)) 

else: 

num = int(self._nrows * self._ncols * density) 

for i from 0 <= i < num: 

self.set_unsafe(randint(0, self._nrows - 1), 

randint(0, self._ncols - 1), 

R._random_nonzero_element(*args, **kwds)) 

else: 

if density >= 1: 

for i from 0 <= i < self._nrows: 

for j from 0 <= j < self._ncols: 

self.set_unsafe(i, j, R.random_element(*args, **kwds)) 

else: 

num = int(self._nrows * self._ncols * density) 

for i from 0 <= i < num: 

self.set_unsafe(randint(0, self._nrows - 1), 

randint(0, self._ncols - 1), 

R.random_element(*args, **kwds)) 

  

def is_one(self): 

""" 

Return True if this matrix is the identity matrix. 

  

EXAMPLES:: 

  

sage: m = matrix(QQ,2,2,range(4)) 

sage: m.is_one() 

False 

sage: m = matrix(QQ,2,[5,0,0,5]) 

sage: m.is_one() 

False 

sage: m = matrix(QQ,2,[1,0,0,1]) 

sage: m.is_one() 

True 

sage: m = matrix(QQ,2,[1,1,1,1]) 

sage: m.is_one() 

False 

""" 

return self.is_scalar(self.base_ring().one()) 

  

def is_scalar(self, a = None): 

""" 

Return True if this matrix is a scalar matrix. 

  

INPUT: 

  

- base_ring element a, which is chosen as self[0][0] if 

a = None 

  

OUTPUT: 

  

- whether self is a scalar matrix (in fact the scalar matrix 

aI if a is input) 

  

EXAMPLES:: 

  

sage: m = matrix(QQ,2,2,range(4)) 

sage: m.is_scalar(5) 

False 

sage: m = matrix(QQ,2,[5,0,0,5]) 

sage: m.is_scalar(5) 

True 

sage: m = matrix(QQ,2,[1,0,0,1]) 

sage: m.is_scalar(1) 

True 

sage: m = matrix(QQ,2,[1,1,1,1]) 

sage: m.is_scalar(1) 

False 

""" 

if not self.is_square(): 

return False 

cdef Py_ssize_t i, j 

if a is None: 

if self._nrows == 0: 

return True 

a = self.get_unsafe(0,0) 

else: 

a = self.base_ring()(a) 

for i in range(self._nrows): 

for j in range(self._ncols): 

if i != j: 

if not self.get_unsafe(i,j).is_zero(): 

return False 

else: 

if self.get_unsafe(i, i) != a: 

return False 

return True 

  

def is_unitary(self): 

r""" 

Returns ``True`` if the columns of the matrix are an orthonormal basis. 

  

For a matrix with real entries this determines if a matrix is 

"orthogonal" and for a matrix with complex entries this determines 

if the matrix is "unitary." 

  

OUTPUT: 

  

``True`` if the matrix is square and its conjugate-transpose is 

its inverse, and ``False`` otherwise. In other words, a matrix 

is orthogonal or unitary if the product of its conjugate-transpose 

times the matrix is the identity matrix. 

  

For numerical matrices a specialized routine available 

over ``RDF`` and ``CDF`` is a good choice. 

  

EXAMPLES:: 

  

sage: A = matrix(QQbar, [[(1/sqrt(5))*(1+i), (1/sqrt(55))*(3+2*I), (1/sqrt(22))*(2+2*I)], 

....: [(1/sqrt(5))*(1-i), (1/sqrt(55))*(2+2*I), (1/sqrt(22))*(-3+I)], 

....: [ (1/sqrt(5))*I, (1/sqrt(55))*(3-5*I), (1/sqrt(22))*(-2)]]) 

sage: A.is_unitary() 

True 

  

A permutation matrix is always orthogonal. :: 

  

sage: sigma = Permutation([1,3,4,5,2]) 

sage: P = sigma.to_matrix(); P 

[1 0 0 0 0] 

[0 0 0 0 1] 

[0 1 0 0 0] 

[0 0 1 0 0] 

[0 0 0 1 0] 

sage: P.is_unitary() 

True 

sage: P.change_ring(GF(3)).is_unitary() 

True 

sage: P.change_ring(GF(3)).is_unitary() 

True 

  

A square matrix far from unitary. :: 

  

sage: A = matrix(QQ, 4, range(16)) 

sage: A.is_unitary() 

False 

  

Rectangular matrices are never unitary. :: 

  

sage: A = matrix(QQbar, 3, 4) 

sage: A.is_unitary() 

False 

""" 

if not self.is_square(): 

return False 

if hasattr(self.base_ring().an_element(), 'conjugate'): 

P = self.conjugate().transpose() * self # Unitary 

else: 

P = self.transpose() * self # Orthogonal 

return P.is_scalar(1) 

  

def is_bistochastic(self, normalized = True): 

r""" 

Returns ``True`` if this matrix is bistochastic. 

  

A matrix is said to be bistochastic if both the sums of the 

entries of each row and the sum of the entries of each column 

are equal to 1 and all entries are nonnegative. 

  

INPUT: 

  

- ``normalized`` -- if set to ``True`` (default), checks that 

the sums are equal to 1. When set to ``False``, checks that 

the row sums and column sums are all equal to some constant 

possibly different from 1. 

  

EXAMPLES: 

  

The identity matrix is clearly bistochastic:: 

  

sage: Matrix(5,5,1).is_bistochastic() 

True 

  

The same matrix, multiplied by 2, is not bistochastic anymore, 

though is verifies the constraints of ``normalized == False``:: 

  

sage: (2 * Matrix(5,5,1)).is_bistochastic() 

False 

sage: (2 * Matrix(5,5,1)).is_bistochastic(normalized = False) 

True 

  

Here is a matrix whose row and column sums is 1, but not all entries are 

nonnegative:: 

  

sage: m = matrix([[-1,2],[2,-1]]) 

sage: m.is_bistochastic() 

False 

""" 

  

row_sums = map(sum, self.rows()) 

col_sums = map(sum, self.columns()) 

  

return self.is_square() and\ 

col_sums[0] == row_sums[0] and\ 

row_sums == col_sums and\ 

row_sums == len(row_sums) * [col_sums[0]] and\ 

((not normalized) or col_sums[0] == self.base_ring()(1)) and\ 

all(entry>=0 for row in self for entry in row) 

  

def is_normal(self): 

r""" 

Returns ``True`` if the matrix commutes with its conjugate-transpose. 

  

OUTPUT: 

  

``True`` if the matrix is square and commutes with its 

conjugate-transpose, and ``False`` otherwise. 

  

Normal matrices are precisely those that can be diagonalized 

by a unitary matrix. 

  

This routine is for matrices over exact rings and so may not 

work properly for matrices over ``RR`` or ``CC``. For matrices with 

approximate entries, the rings of double-precision floating-point 

numbers, ``RDF`` and ``CDF``, are a better choice since the 

:meth:`sage.matrix.matrix_double_dense.Matrix_double_dense.is_normal` 

method has a tolerance parameter. This provides control over 

allowing for minor discrepancies between entries when checking 

equality. 

  

The result is cached. 

  

EXAMPLES: 

  

Hermitian matrices are normal. :: 

  

sage: A = matrix(QQ, 5, 5, range(25)) + I*matrix(QQ, 5, 5, range(0, 50, 2)) 

sage: B = A*A.conjugate_transpose() 

sage: B.is_hermitian() 

True 

sage: B.is_normal() 

True 

  

Circulant matrices are normal. :: 

  

sage: G = graphs.CirculantGraph(20, [3, 7]) 

sage: D = digraphs.Circuit(20) 

sage: A = 3*D.adjacency_matrix() - 5*G.adjacency_matrix() 

sage: A.is_normal() 

True 

  

Skew-symmetric matrices are normal. :: 

  

sage: A = matrix(QQ, 5, 5, range(25)) 

sage: B = A - A.transpose() 

sage: B.is_skew_symmetric() 

True 

sage: B.is_normal() 

True 

  

A small matrix that does not fit into any of the usual categories 

of normal matrices. :: 

  

sage: A = matrix(ZZ, [[1, -1], 

....: [1, 1]]) 

sage: A.is_normal() 

True 

sage: not A.is_hermitian() and not A.is_skew_symmetric() 

True 

  

Sage has several fields besides the entire complex numbers 

where conjugation is non-trivial. :: 

  

sage: F.<b> = QuadraticField(-7) 

sage: C = matrix(F, [[-2*b - 3, 7*b - 6, -b + 3], 

....: [-2*b - 3, -3*b + 2, -2*b], 

....: [ b + 1, 0, -2]]) 

sage: C = C*C.conjugate_transpose() 

sage: C.is_normal() 

True 

  

A matrix that is nearly normal, but for a non-real 

diagonal entry. :: 

  

sage: A = matrix(QQbar, [[ 2, 2-I, 1+4*I], 

....: [ 2+I, 3+I, 2-6*I], 

....: [1-4*I, 2+6*I, 5]]) 

sage: A.is_normal() 

False 

sage: A[1,1] = 132 

sage: A.is_normal() 

True 

  

Rectangular matrices are never normal. :: 

  

sage: A = matrix(QQbar, 3, 4) 

sage: A.is_normal() 

False 

  

A square, empty matrix is trivially normal. :: 

  

sage: A = matrix(QQ, 0, 0) 

sage: A.is_normal() 

True 

  

AUTHOR: 

  

- Rob Beezer (2011-03-31) 

""" 

key = 'normal' 

n = self.fetch(key) 

if not n is None: 

return n 

if not self.is_square(): 

self.cache(key, False) 

return False 

if self._nrows == 0: 

self.cache(key, True) 

return True 

  

CT = self.conjugate_transpose() 

cdef Matrix left = self*CT 

cdef Matrix right = CT*self 

  

cdef Py_ssize_t i,j 

normal = True 

# two products are Hermitian, need only check lower triangle 

for i from 0 <= i < self._nrows: 

for j from 0 <= j <= i: 

if left.get_unsafe(i,j) != right.get_unsafe(i,j): 

normal = False 

break 

if not normal: 

break 

self.cache(key, normal) 

return normal 

  

def as_sum_of_permutations(self): 

r""" 

Returns the current matrix as a sum of permutation matrices 

  

According to the Birkhoff-von Neumann Theorem, any bistochastic matrix 

can be written as a positive sum of permutation matrices, which also 

means that the polytope of bistochastic matrices is integer. 

  

As a non-bistochastic matrix can obviously not be written as a sum of 

permutations, this theorem is an equivalence. 

  

This function, given a bistochastic matrix, returns the corresponding 

decomposition. 

  

.. SEEALSO:: 

  

- :func:`bistochastic_as_sum_of_permutations 

<sage.combinat.permutation.bistochastic_as_sum_of_permutations>` 

-- for more information on this method. 

  

- :meth:`~sage.geometry.polyhedron.library.Polytopes.Birkhoff_polytope` 

  

EXAMPLES: 

  

We create a bistochastic matrix from a convex sum of permutations, then 

try to deduce the decomposition from the matrix :: 

  

sage: L = [] 

sage: L.append((9,Permutation([4, 1, 3, 5, 2]))) 

sage: L.append((6,Permutation([5, 3, 4, 1, 2]))) 

sage: L.append((3,Permutation([3, 1, 4, 2, 5]))) 

sage: L.append((2,Permutation([1, 4, 2, 3, 5]))) 

sage: M = sum([c * p.to_matrix() for (c,p) in L]) 

sage: decomp = sage.combinat.permutation.bistochastic_as_sum_of_permutations(M) 

sage: print(decomp) 

2*B[[1, 4, 2, 3, 5]] + 3*B[[3, 1, 4, 2, 5]] + 9*B[[4, 1, 3, 5, 2]] + 6*B[[5, 3, 4, 1, 2]] 

  

An exception is raised when the matrix is not bistochastic:: 

  

sage: M = Matrix([[2,3],[2,2]]) 

sage: decomp = sage.combinat.permutation.bistochastic_as_sum_of_permutations(M) 

Traceback (most recent call last): 

... 

ValueError: The matrix is not bistochastic 

""" 

  

from sage.combinat.permutation import bistochastic_as_sum_of_permutations 

return bistochastic_as_sum_of_permutations(self) 

  

def visualize_structure(self, maxsize=512): 

r""" 

Visualize the non-zero entries 

  

White pixels are put at positions with zero entries. If 'maxsize' 

is given, then the maximal dimension in either x or y direction is 

set to 'maxsize' depending on which is bigger. If the image is 

scaled, the darkness of the pixel reflects how many of the 

represented entries are nonzero. So if e.g. one image pixel 

actually represents a 2x2 submatrix, the dot is darker the more of 

the four values are nonzero. 

  

INPUT: 

  

- ``maxsize`` - integer (default: ``512``). Maximal dimension 

in either x or y direction of the resulting image. If 

``None`` or a maxsize larger than 

``max(self.nrows(),self.ncols())`` is given the image will 

have the same pixelsize as the matrix dimensions. 

  

OUTPUT: 

  

Bitmap image as an instance of 

:class:`~sage.repl.image.Image`. 

  

EXAMPLES:: 

  

sage: M = random_matrix(CC, 5, 7) 

sage: for i in range(5): M[i,i] = 0 

sage: M[4, 0] = M[0, 6] = M[4, 6] = 0 

sage: img = M.visualize_structure(); img 

7x5px 24-bit RGB image 

  

You can use :meth:`~sage.repl.image.Image.save` to save the 

resulting image:: 

  

sage: filename = tmp_filename(ext='.png') 

sage: img.save(filename) 

sage: open(filename).read().startswith('\x89PNG') 

True 

  

TESTS: 

  

Test :trac:`17341`:: 

  

sage: random_matrix(GF(2), 8, 586, sparse=True).visualize_structure() 

512x6px 24-bit RGB image 

""" 

cdef Py_ssize_t x, y, _x, _y, v, bi, bisq 

cdef Py_ssize_t ir, ic 

cdef double b, fct 

mr, mc = self.nrows(), self.ncols() 

if maxsize is None: 

ir = mc 

ic = mr 

b = 1.0 

elif max(mr,mc) > maxsize: 

maxsize = float(maxsize) 

ir = int(mc * maxsize/max(mr,mc)) 

ic = int(mr * maxsize/max(mr,mc)) 

b = max(mr,mc)/maxsize 

else: 

ir = mc 

ic = mr 

b = 1.0 

bi = int(round(b)) 

bisq = bi*bi 

fct = 255.0/bisq 

from sage.repl.image import Image 

img = Image('RGB', (ir, ic)) 

pixel = img.pixels() 

for x in range(ic): 

for y in range(ir): 

v = bisq 

for _x in range(bi): 

for _y in range(bi): 

if not self.get_unsafe(<Py_ssize_t>(x*b + _x), <Py_ssize_t>(y*b + _y)).is_zero(): 

v -= 1 #increase darkness 

v = <Py_ssize_t>(v * fct + 0.5) 

pixel[y, x] = (v, v, v) 

return img 

  

def density(self): 

""" 

Return the density of the matrix. 

  

By density we understand the ratio of the number of nonzero 

positions and the self.nrows() \* self.ncols(), i.e. the number of 

possible nonzero positions. 

  

EXAMPLES: 

  

First, note that the density parameter does not ensure the density 

of a matrix, it is only an upper bound. 

  

:: 

  

sage: A = random_matrix(GF(127),200,200,density=0.3) 

sage: A.density() 

5211/20000 

  

:: 

  

sage: A = matrix(QQ,3,3,[0,1,2,3,0,0,6,7,8]) 

sage: A.density() 

2/3 

  

:: 

  

sage: a = matrix([[],[],[],[]]) 

sage: a.density() 

0 

""" 

cdef int x,y,k 

k = 0 

nr = self.nrows() 

nc = self.ncols() 

if nc == 0 or nr == 0: 

return 0 

for x from 0 <= x < nr: 

for y from 0 <= y < nc: 

if not self.get_unsafe(x,y).is_zero(): 

k+=1 

return QQ(k)/QQ(nr*nc) 

  

def inverse(self): 

""" 

Returns the inverse of self, without changing self. 

  

Note that one can use the Python inverse operator to obtain the 

inverse as well. 

  

EXAMPLES:: 

  

sage: m = matrix([[1,2],[3,4]]) 

sage: m^(-1) 

[ -2 1] 

[ 3/2 -1/2] 

sage: m.inverse() 

[ -2 1] 

[ 3/2 -1/2] 

sage: ~m 

[ -2 1] 

[ 3/2 -1/2] 

  

:: 

  

sage: m = matrix([[1,2],[3,4]], sparse=True) 

sage: m^(-1) 

[ -2 1] 

[ 3/2 -1/2] 

sage: m.inverse() 

[ -2 1] 

[ 3/2 -1/2] 

sage: ~m 

[ -2 1] 

[ 3/2 -1/2] 

  

TESTS:: 

  

sage: matrix().inverse() 

[] 

""" 

return ~self 

  

def adjoint(self): 

""" 

Returns the adjoint matrix of self (matrix of cofactors). 

  

OUTPUT: 

  

- ``N`` - the adjoint matrix, such that 

N \* M = M \* N = M.parent(M.det()) 

  

ALGORITHM: 

  

Use PARI whenever the method ``self._adjoint`` is included to do so 

in an inheriting class. Otherwise, use a generic division-free 

algorithm to compute the characteristic polynomial and hence the 

adjoint. 

  

The result is cached. 

  

EXAMPLES:: 

  

sage: M = Matrix(ZZ,2,2,[5,2,3,4]) ; M 

[5 2] 

[3 4] 

sage: N = M.adjoint() ; N 

[ 4 -2] 

[-3 5] 

sage: M * N 

[14 0] 

[ 0 14] 

sage: N * M 

[14 0] 

[ 0 14] 

sage: M = Matrix(QQ,2,2,[5/3,2/56,33/13,41/10]) ; M 

[ 5/3 1/28] 

[33/13 41/10] 

sage: N = M.adjoint() ; N 

[ 41/10 -1/28] 

[-33/13 5/3] 

sage: M * N 

[7363/1092 0] 

[ 0 7363/1092] 

  

AUTHORS: 

  

- Unknown: No author specified in the file from 2009-06-25 

- Sebastian Pancratz (2009-06-25): Reflecting the change that 

``_adjoint`` is now implemented in this class 

""" 

  

if self._nrows != self._ncols: 

raise ValueError("self must be a square matrix") 

  

X = self.fetch('adjoint') 

if not X is None: 

return X 

  

X = self._adjoint() 

self.cache('adjoint', X) 

return X 

  

def _adjoint(self): 

r""" 

Returns the adjoint of self. 

  

OUTPUT: 

  

- matrix -- the adjoint of self 

  

EXAMPLES: 

  

Here is one example to illustrate this:: 

  

sage: A = matrix(ZZ, [[1,24],[3,5]]) 

sage: A 

[ 1 24] 

[ 3 5] 

sage: A._adjoint() 

[ 5 -24] 

[ -3 1] 

  

Secondly, here is an example over a polynomial ring:: 

  

sage: R.<t> = QQ[] 

sage: A = matrix(R, [[-2*t^2 + t + 3/2, 7*t^2 + 1/2*t - 1, \ 

-6*t^2 + t - 2/11], \ 

[-7/3*t^2 - 1/2*t - 1/15, -2*t^2 + 19/8*t, \ 

-10*t^2 + 2*t + 1/2], \ 

[6*t^2 - 1/2, -1/7*t^2 + 9/4*t, -t^2 - 4*t \ 

- 1/10]]) 

sage: A 

[ -2*t^2 + t + 3/2 7*t^2 + 1/2*t - 1 -6*t^2 + t - 2/11] 

[-7/3*t^2 - 1/2*t - 1/15 -2*t^2 + 19/8*t -10*t^2 + 2*t + 1/2] 

[ 6*t^2 - 1/2 -1/7*t^2 + 9/4*t -t^2 - 4*t - 1/10] 

sage: A._adjoint() 

[ 4/7*t^4 + 1591/56*t^3 - 961/70*t^2 - 109/80*t 55/7*t^4 + 104/7*t^3 + 6123/1540*t^2 - 959/220*t - 1/10 -82*t^4 + 101/4*t^3 + 1035/88*t^2 - 29/22*t - 1/2] 

[ -187/3*t^4 + 13/6*t^3 + 57/10*t^2 - 79/60*t - 77/300 38*t^4 + t^3 - 793/110*t^2 - 28/5*t - 53/220 -6*t^4 + 44/3*t^3 + 4727/330*t^2 - 1147/330*t - 487/660] 

[ 37/3*t^4 - 136/7*t^3 - 1777/840*t^2 + 83/80*t 292/7*t^4 + 107/14*t^3 - 323/28*t^2 - 29/8*t + 1/2 61/3*t^4 - 25/12*t^3 - 269/120*t^2 + 743/240*t - 1/15] 

  

Finally, an example over a general ring, that is to say, as of 

version 4.0.2, SAGE does not even determine that ``S`` in the following 

example is an integral domain:: 

  

sage: R.<a,b> = QQ[] 

sage: S.<x,y> = R.quo((b^3)) 

sage: A = matrix(S, [[x*y^2,2*x],[2,x^10*y]]) 

sage: A 

[ x*y^2 2*x] 

[ 2 x^10*y] 

sage: A.det() 

-4*x 

sage: A.charpoly('T') 

T^2 + (-x^10*y - x*y^2)*T - 4*x 

sage: A.adjoint() 

[x^10*y -2*x] 

[ -2 x*y^2] 

sage: A.adjoint() * A 

[-4*x 0] 

[ 0 -4*x] 

  

TESTS: 

  

Ensure correct handling of very small matrices:: 

  

sage: A = matrix(ZZ, 0, 0) 

sage: A 

[] 

sage: A._adjoint() 

[] 

sage: A = matrix(ZZ, [[2]]) 

sage: A 

[2] 

sage: A._adjoint() 

[1] 

  

Ensure proper computation of the adjoint matrix even in the 

presence of non-integral powers of the variable `x` 

(:trac:`14403`):: 

  

sage: x = var('x') 

sage: Matrix([[sqrt(x),x],[1,0]]).adjoint() 

[ 0 -x] 

[ -1 sqrt(x)] 

  

NOTES: 

  

The key feature of this implementation is that it is division-free. 

This means that it can be used as a generic implementation for any 

ring (commutative and with multiplicative identity). The algorithm 

is described in full detail as Algorithm 3.1 in [Se02]. 

  

Note that this method does not utilise a lookup if the adjoint has 

already been computed previously, and it does not cache the result. 

This is all left to the method `adjoint`. 

  

REFERENCES: 

  

- [Se02] T. R. Seifullin, "Computation of determinants, adjoint 

matrices, and characteristic polynomials without division" 

  

AUTHORS: 

  

- Sebastian Pancratz (2009-06-12): Initial version 

""" 

  

# Validate assertions 

# 

if self._nrows != self._ncols: 

raise ValueError("self must be a square matrix") 

  

# Corner cases 

# N.B. We already tested for the matrix to be square, hence we do not 

# need to test for 0 x n or m x 0 matrices. 

# 

if self._ncols == 0: 

return self.copy() 

  

# Extract parameters 

# 

n = self._ncols 

R = self._base_ring 

MS = self._parent 

  

f = self.charpoly() 

  

# Let A denote the adjoint of M, which we want to compute, and 

# N denote a copy of M used to store powers of M. 

# 

A = f[1] * MS.identity_matrix() 

N = R(1) * MS.identity_matrix() 

for i in range(1, n): 

# Set N to be M^i 

# 

N = N * self 

A = A + f[i+1] * N 

if not (n % 2): 

A = - A 

  

return A 

  

def QR(self, full=True): 

r""" 

Returns a factorization of ``self`` as a unitary matrix 

and an upper-triangular matrix. 

  

INPUT: 

  

- ``full`` - default: ``True`` - if ``True`` then the 

returned matrices have dimensions as described below. 

If ``False`` the ``R`` matrix has no zero rows and the 

columns of ``Q`` are a basis for the column space of 

``self``. 

  

OUTPUT: 

  

If ``self`` is an `m\times n` matrix and ``full=True`` then this 

method returns a pair of matrices: `Q` is an `m\times m` unitary 

matrix (meaning its inverse is its conjugate-transpose) and `R` 

is an `m\times n` upper-triangular matrix with non-negative entries 

on the diagonal. For a matrix of full rank this factorization is 

unique (due to the restriction to positive entries on the diagonal). 

  

If ``full=False`` then `Q` has `m` rows and the columns form an 

orthonormal basis for the column space of ``self``. So, in particular, 

the conjugate-transpose of `Q` times `Q` will be an identity matrix. 

The matrix `R` will still be upper-triangular but will also have full 

rank, in particular it will lack the zero rows present in a full 

factorization of a rank-deficient matrix. 

  

The results obtained when ``full=True`` are cached, 

hence `Q` and `R` are immutable matrices in this case. 

  

.. NOTE:: 

  

This is an exact computation, so limited to exact rings. 

Also the base ring needs to have a fraction field implemented 

in Sage and this field must contain square roots. One example 

is the field of algebraic numbers, ``QQbar``, as used in the 

examples below. If you need numerical results, convert the 

base ring to the field of complex double numbers, ``CDF``, 

which will use a faster routine that is careful about 

numerical subtleties. 

  

ALGORITHM: 

  

"Modified Gram-Schmidt," Algorithm 8.1 of [TB1997]_. 

  

EXAMPLES: 

  

For a nonsingular matrix, the QR decomposition is unique. :: 

  

sage: A = matrix(QQbar, [[-2, 0, -4, -1, -1], 

....: [-2, 1, -6, -3, -1], 

....: [1, 1, 7, 4, 5], 

....: [3, 0, 8, 3, 3], 

....: [-1, 1, -6, -6, 5]]) 

sage: Q, R = A.QR() 

sage: Q 

[ -0.4588314677411235? -0.1260506983326509? 0.3812120831224489? -0.394573711338418? -0.6874400625964?] 

[ -0.4588314677411235? 0.4726901187474409? -0.05198346588033394? 0.7172941251646595? -0.2209628772631?] 

[ 0.2294157338705618? 0.6617661662464172? 0.6619227988762521? -0.1808720937375480? 0.1964114464561?] 

[ 0.6882472016116853? 0.1890760474989764? -0.2044682991293135? 0.0966302966543065? -0.6628886317894?] 

[ -0.2294157338705618? 0.5357154679137663? -0.609939332995919? -0.536422031427112? 0.0245514308070?] 

sage: R 

[ 4.358898943540674? -0.4588314677411235? 13.07669683062202? 6.194224814505168? 2.982404540317303?] 

[ 0 1.670171752907625? 0.5987408170800917? -1.292019657909672? 6.207996892883057?] 

[ 0 0 5.444401659866974? 5.468660610611130? -0.6827161852283857?] 

[ 0 0 0 1.027626039419836? -3.619300149686620?] 

[ 0 0 0 0 0.024551430807012?] 

sage: Q.conjugate_transpose()*Q 

[1.000000000000000? 0.?e-18 0.?e-17 0.?e-16 0.?e-13] 

[ 0.?e-18 1.000000000000000? 0.?e-17 0.?e-16 0.?e-13] 

[ 0.?e-17 0.?e-17 1.000000000000000? 0.?e-16 0.?e-13] 

[ 0.?e-16 0.?e-16 0.?e-16 1.000000000000000? 0.?e-13] 

[ 0.?e-13 0.?e-13 0.?e-13 0.?e-13 1.0000000000000?] 

sage: Q*R == A 

True 

  

  

An example with complex numbers in ``QQbar``, the field of algebraic 

numbers. :: 

  

sage: A = matrix(QQbar, [[-8, 4*I + 1, -I + 2, 2*I + 1], 

....: [1, -2*I - 1, -I + 3, -I + 1], 

....: [I + 7, 2*I + 1, -2*I + 7, -I + 1], 

....: [I + 2, 0, I + 12, -1]]) 

sage: Q, R = A.QR() 

sage: Q 

[ -0.7302967433402215? 0.2070566455055649? + 0.5383472783144687?*I 0.2463049809998642? - 0.0764456358723292?*I 0.2381617683194332? - 0.1036596032779695?*I] 

[ 0.0912870929175277? -0.2070566455055649? - 0.3778783780476559?*I 0.3786559533863033? - 0.1952221495524667?*I 0.701244450214469? - 0.3643711650986595?*I] 

[ 0.6390096504226938? + 0.0912870929175277?*I 0.1708217325420910? + 0.6677576817554466?*I -0.03411475806452072? + 0.04090198741767143?*I 0.3140171085506764? - 0.0825191718705412?*I] 

[ 0.1825741858350554? + 0.0912870929175277?*I -0.03623491296347385? + 0.0724698259269477?*I 0.8632284069415110? + 0.06322839976356195?*I -0.4499694867611521? - 0.0116119181208918?*I] 

sage: R 

[ 10.95445115010333? 0.?e-18 - 1.917028951268082?*I 5.385938482134133? - 2.190890230020665?*I -0.2738612787525831? - 2.190890230020665?*I] 

[ 0 4.829596256417300? + 0.?e-18*I -0.869637911123373? - 5.864879483945125?*I 0.993871898426712? - 0.3054085521207082?*I] 

[ 0 0 12.00160760935814? + 0.?e-16*I -0.2709533402297273? + 0.4420629644486323?*I] 

[ 0 0 0 1.942963944258992? + 0.?e-16*I] 

sage: Q.conjugate_transpose()*Q 

[1.000000000000000? + 0.?e-19*I 0.?e-18 + 0.?e-17*I 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I] 

[ 0.?e-18 + 0.?e-17*I 1.000000000000000? + 0.?e-17*I 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I] 

[ 0.?e-17 + 0.?e-17*I 0.?e-17 + 0.?e-17*I 1.000000000000000? + 0.?e-17*I 0.?e-16 + 0.?e-16*I] 

[ 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I 1.000000000000000? + 0.?e-16*I] 

sage: Q*R - A 

[ 0.?e-17 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I] 

[ 0.?e-18 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I] 

[0.?e-17 + 0.?e-18*I 0.?e-17 + 0.?e-17*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I] 

[0.?e-18 + 0.?e-18*I 0.?e-18 + 0.?e-18*I 0.?e-16 + 0.?e-16*I 0.?e-16 + 0.?e-16*I] 

  

A rank-deficient rectangular matrix, with both values of the ``full`` keyword. :: 

  

sage: A = matrix(QQbar, [[2, -3, 3], 

....: [-1, 1, -1], 

....: [-1, 3, -3], 

....: [-5, 1, -1]]) 

sage: Q, R = A.QR() 

sage: Q 

[ 0.3592106040535498? -0.5693261797050169? 0.7239227659930268? 0.1509015305256380?] 

[ -0.1796053020267749? 0.1445907757980996? 0 0.9730546968377341?] 

[ -0.1796053020267749? 0.7048800320157352? 0.672213996993525? -0.1378927778941174?] 

[ -0.8980265101338745? -0.3976246334447737? 0.1551263069985058? -0.10667177157846818?] 

sage: R 

[ 5.567764362830022? -2.694079530401624? 2.694079530401624?] 

[ 0 3.569584777515583? -3.569584777515583?] 

[ 0 0 0] 

[ 0 0 0] 

sage: Q.conjugate_transpose()*Q 

[ 1 0.?e-18 0.?e-18 0.?e-18] 

[ 0.?e-18 1 0.?e-18 0.?e-18] 

[ 0.?e-18 0.?e-18 1.000000000000000? 0.?e-18] 

[ 0.?e-18 0.?e-18 0.?e-18 1.000000000000000?] 

  

sage: Q, R = A.QR(full=False) 

sage: Q 

[ 0.3592106040535498? -0.5693261797050169?] 

[-0.1796053020267749? 0.1445907757980996?] 

[-0.1796053020267749? 0.7048800320157352?] 

[-0.8980265101338745? -0.3976246334447737?] 

sage: R 

[ 5.567764362830022? -2.694079530401624? 2.694079530401624?] 

[ 0 3.569584777515583? -3.569584777515583?] 

sage: Q.conjugate_transpose()*Q 

[ 1 0.?e-18] 

[0.?e-18 1] 

  

Another rank-deficient rectangular matrix, with complex entries, 

as a reduced decomposition. :: 

  

sage: A = matrix(QQbar, [[-3*I - 3, I - 3, -12*I + 1, -2], 

....: [-I - 1, -2, 5*I - 1, -I - 2], 

....: [-4*I - 4, I - 5, -7*I, -I - 4]]) 

sage: Q, R = A.QR(full=False) 

sage: Q 

[ -0.4160251471689219? - 0.4160251471689219?*I 0.5370861555295747? + 0.1790287185098583?*I] 

[ -0.1386750490563073? - 0.1386750490563073?*I -0.7519206177414046? - 0.2506402059138015?*I] 

[ -0.5547001962252291? - 0.5547001962252291?*I -0.2148344622118299? - 0.07161148740394329?*I] 

sage: R 

[ 7.211102550927979? 3.328201177351375? - 5.269651864139676?*I 7.904477796209515? + 8.45917799243475?*I 4.021576422632911? - 2.634825932069838?*I] 

[ 0 1.074172311059150? -1.611258466588724? - 9.13046464400277?*I 1.611258466588724? + 0.5370861555295747?*I] 

sage: Q.conjugate_transpose()*Q 

[1 0] 

[0 1] 

sage: Q*R-A 

[0 0 0 0] 

[0 0 0 0] 

[0 0 0 0] 

  

Results of full decompositions are cached and thus returned 

immutable. :: 

  

sage: A = random_matrix(QQbar, 2, 2) 

sage: Q, R = A.QR() 

sage: Q.is_mutable() 

False 

sage: R.is_mutable() 

False 

  

Trivial cases return trivial results of the correct size, 

and we check `Q` itself in one case. :: 

  

sage: A = zero_matrix(QQbar, 0, 10) 

sage: Q, R = A.QR() 

sage: Q.nrows(), Q.ncols() 

(0, 0) 

sage: R.nrows(), R.ncols() 

(0, 10) 

sage: A = zero_matrix(QQbar, 3, 0) 

sage: Q, R = A.QR() 

sage: Q.nrows(), Q.ncols() 

(3, 3) 

sage: R.nrows(), R.ncols() 

(3, 0) 

sage: Q 

[1 0 0] 

[0 1 0] 

[0 0 1] 

  

TESTS: 

  

Inexact rings are caught and ``CDF`` suggested. :: 

  

sage: A = matrix(RealField(100), 2, 2, range(4)) 

sage: A.QR() 

Traceback (most recent call last): 

... 

NotImplementedError: QR decomposition is implemented over exact rings, try CDF for numerical results, not Real Field with 100 bits of precision 

  

Without a fraction field, we cannot hope to run the algorithm. :: 

  

sage: A = matrix(Integers(6), 2, 2, range(4)) 

sage: A.QR() 

Traceback (most recent call last): 

... 

ValueError: QR decomposition needs a fraction field of Ring of integers modulo 6 

  

The biggest obstacle is making unit vectors, thus requiring square 

roots, though some small cases pass through. :: 

  

sage: A = matrix(ZZ, 3, 3, range(9)) 

sage: A.QR() 

Traceback (most recent call last): 

... 

TypeError: QR decomposition unable to compute square roots in Rational Field 

  

sage: A = matrix(ZZ, 2, 2, range(4)) 

sage: Q, R = A.QR() 

sage: Q 

[0 1] 

[1 0] 

sage: R 

[2 3] 

[0 1] 

  

AUTHOR: 

  

- Rob Beezer (2011-02-17) 

""" 

from sage.modules.free_module_element import zero_vector 

from sage.matrix.constructor import zero_matrix, matrix 

from sage.functions.other import sqrt 

  

if full: 

QR = self.fetch('QR_factors') 

if QR is not None: 

return QR 

R = self.base_ring() 

if not R.is_exact(): 

raise NotImplementedError('QR decomposition is implemented over exact rings, try CDF for numerical results, not %s' % R) 

try: 

F = R.fraction_field() 

except Exception: 

raise ValueError("QR decomposition needs a fraction field of %s" % R) 

m = self.nrows() 

n = self.ncols() 

  

R = zero_matrix(F, m, n) 

V = self.columns(copy=True) 

Q = [] 

row = 0 # row of R being filled 

for i in range(n): 

v = V[i] 

hip = v.hermitian_inner_product(v) 

if hip != 0: 

try: 

scale = sqrt(hip) 

q = (1/scale)*v 

Q.append(q) 

R[row,i] = scale 

for j in range(i+1, n): 

R[row,j] = q.hermitian_inner_product(V[j]) 

V[j] = V[j] - R[row,j]*q 

row = row + 1 

except TypeError: 

raise TypeError('QR decomposition unable to compute square roots in %s' % F) 

# complete to full orthonormal basis, or reduce to truncated R 

if full: 

Qt = matrix(Q) # as rows here 

if Qt.nrows() == 0: 

Qt = zero_matrix(F, 0, m) 

orthogonal = Qt.right_kernel().basis_matrix().transpose() 

Qperp, _ = orthogonal.QR(full=False) 

Q = Q + Qperp.columns() 

else: 

R = R[0:len(Q), 0:n] 

Q = matrix(Q).transpose() 

# Adjust rows of Q if empty 

if Q.ncols() == 0: 

Q = zero_matrix(F, m, 0) 

QR = (Q, R) 

if full: 

Q.set_immutable() 

R.set_immutable() 

self.cache('QR_factors', QR) 

return QR 

  

def _gram_schmidt_noscale(self): 

r""" 

Performs Gram-Schmidt orthogonalization, with no scaling to unit vectors. 

  

INPUT: 

  

- ``self`` - is a matrix whose columns are to be orthogonalized. 

The base ring of the matrix needs to have its fraction field 

implemented. 

  

OUTPUT: 

  

Two matrices, ``Q`` and ``R`` such that if ``A`` represents ``self``: 

  

- ``A = Q*R`` 

- The columns of ``Q`` are an orthogonal set which spans the 

column space of ``A``. 

- The conjugate-transpose of ``Q`` times ``Q`` is a diagonal matrix. 

- ``R`` is a full-rank matrix, that has all entries below the 

main diagonal equal to zero. 

  

This is basically a "reduced" QR decomposition of ``self`` with 

the distinction that the orthogonal column vectors of ``Q`` have 

not been scaled to unit vectors, avoiding the need to take square 

roots. 

  

EXAMPLES: 

  

A rectangular matrix whose columns have full-rank. Notice that the 

routine computes in the fraction field, requiring the column space 

check to step up to ``QQ``. :: 

  

sage: A = matrix(ZZ, [[-1, -3, 0, -1], 

....: [ 1, 2, -1, 2], 

....: [-3, -6, 4, -7]]) 

sage: Q,R = A._gram_schmidt_noscale() 

sage: Q 

[ -1 -10/11 0] 

[ 1 -1/11 3/10] 

[ -3 3/11 1/10] 

sage: R 

[ 1 23/11 -13/11 24/11] 

[ 0 1 13/10 -13/10] 

[ 0 0 1 -1] 

sage: Q*R == A 

True 

sage: Q.transpose()*Q 

[ 11 0 0] 

[ 0 10/11 0] 

[ 0 0 1/10] 

sage: A.change_ring(QQ).column_space() == Q.column_space() 

True 

  

A matrix over a subfield of the complex numbers, with four 

columns but rank 3, so the orthogonal set has just 3 vectors 

as well. Orthogonality comes from the Hermitian inner product 

so we need to check with the conjugate-transpose. This 

example verifies that the bug on :trac:`10791` is fixed. :: 

  

sage: F.<a> = QuadraticField(-5) 

sage: A = matrix(F, [[ 1, a - 3, a - 2, a + 1], 

....: [ a, 2*a + 1, 3*a + 1, 1], 

....: [a + 1, a - 6, 2*a - 5, 1], 

....: [ 2*a, a, 3*a, -3], 

....: [ 1, a - 1, a, a - 1]]) 

sage: A.rank() 

3 

sage: Q, R = A._gram_schmidt_noscale() 

sage: Q 

[ 1 25/33*a - 38/11 641/1163*a + 453/1163] 

[ a 17/11*a + 73/33 322/1163*a + 1566/1163] 

[ a + 1 10/33*a - 173/33 -784/1163*a + 1614/1163] 

[ 2*a 1/11*a + 80/33 196/1163*a - 1234/1163] 

[ 1 25/33*a - 16/11 855/1163*a - 1717/1163] 

sage: R 

[ 1 8/33*a + 5/11 8/33*a + 16/11 2/11*a + 1/33] 

[ 0 1 1 -107/1163*a - 78/1163] 

[ 0 0 0 1] 

sage: Q*R == A 

True 

sage: Q.transpose().conjugate()*Q 

[ 33 0 0] 

[ 0 2326/33 0] 

[ 0 0 16532/1163] 

sage: Q.column_space() == A.column_space() 

True 

  

Some trivial cases. :: 

  

sage: A = matrix(ZZ, 3, 0) 

sage: Q, R = A._gram_schmidt_noscale() 

sage: Q.parent() 

Full MatrixSpace of 3 by 0 dense matrices over Rational Field 

sage: R.parent() 

Full MatrixSpace of 0 by 0 dense matrices over Rational Field 

sage: Q*R == A 

True 

  

sage: A = matrix(ZZ, 0, 3) 

sage: Q, R = A._gram_schmidt_noscale() 

sage: Q.parent() 

Full MatrixSpace of 0 by 0 dense matrices over Rational Field 

sage: R.parent() 

Full MatrixSpace of 0 by 3 dense matrices over Rational Field 

sage: Q*R == A 

True 

  

TESTS: 

  

Without a fraction field, we cannot hope to proceed. :: 

  

sage: A = matrix(Integers(6), 2, 2, range(4)) 

sage: A._gram_schmidt_noscale() 

Traceback (most recent call last): 

... 

TypeError: Gram-Schmidt orthogonalization requires a base ring with a fraction field, not Ring of integers modulo 6 

  

AUTHORS: 

  

- William Stein (2007-11-18) 

- Rob Beezer (2011-02-25) 

""" 

from sage.matrix.constructor import matrix, zero_matrix 

R = self.base_ring() 

try: 

F = R.fraction_field() 

except TypeError: 

raise TypeError("Gram-Schmidt orthogonalization requires a base ring with a fraction field, not %s" % R) 

n = self.ncols() 

B = self.columns() 

zero = F(0) 

Bstar = [] 

R = zero_matrix(F, n) 

nnz = 0 # number non-zero rows in R, or number of nonzero vectors in Bstar 

for i in range(n): 

ortho = B[i] 

for j in range(nnz): 

R[j,i] = Bstar[j].hermitian_inner_product(B[i])/Bstar[j].hermitian_inner_product(Bstar[j]) 

ortho = ortho - R[j,i]*Bstar[j] 

if ortho.hermitian_inner_product(ortho) != zero: 

Bstar.append(ortho) 

R[nnz, i] = 1 

nnz = nnz + 1 

R = R[0:nnz] 

if Bstar == []: 

Q = matrix(F, 0, self.nrows()).transpose() 

else: 

Q = matrix(F, Bstar).transpose() 

return Q, R 

  

def gram_schmidt(self, orthonormal=False): 

r""" 

Performs Gram-Schmidt orthogonalization on the rows of the matrix, 

returning a new matrix and a matrix accomplishing the transformation. 

  

INPUT: 

  

- ``self`` - a matrix whose rows are to be orthogonalized. 

- ``orthonormal`` - default: ``False`` - if ``True`` the 

returned orthogonal vectors are unit vectors. This keyword 

is ignored if the matrix is over ``RDF`` or ``CDF`` and the 

results are always orthonormal. 

  

OUTPUT: 

  

A pair of matrices, ``G`` and ``M`` such that if ``A`` 

represents ``self``, where the parenthetical properties occur 

when ``orthonormal = True``: 

  

- ``A = M*G`` 

- The rows of ``G`` are an orthogonal (resp. orthonormal) 

set of vectors. 

- ``G`` times the conjugate-transpose of ``G`` is a diagonal 

(resp. identity) matrix. 

- The row space of ``G`` equals the row space of ``A``. 

- ``M`` is a full-rank matrix with zeros above the diagonal. 

  

For exact rings, any zero vectors produced (when the original 

vectors are linearly dependent) are not output, thus the 

orthonormal set is linearly independent, and thus a basis for the 

row space of the original matrix. 

  

Any notion of a Gram-Schmidt procedure requires that the base 

ring of the matrix has a fraction field implemented. In order 

to arrive at an orthonormal set, it must be possible to construct 

square roots of the elements of the base field. In Sage, your 

best option is the field of algebraic numbers, ``QQbar``, which 

properly contains the rationals and number fields. 

  

If you have an approximate numerical matrix, then this routine 

requires that your base field be the real and complex 

double-precision floating point numbers, ``RDF`` and ``CDF``. 

In this case, the matrix is treated as having full rank, as no 

attempt is made to recognize linear dependence with approximate 

calculations. 

  

EXAMPLES: 

  

Inexact Rings, Numerical Matrices: 

  

First, the inexact rings, ``CDF`` and ``RDF``. :: 

  

sage: A = matrix(CDF, [[ 0.6454 + 0.7491*I, -0.8662 + 0.1489*I, 0.7656 - 0.00344*I], 

....: [-0.2913 + 0.8057*I, 0.8321 + 0.8170*I, -0.6744 + 0.9248*I], 

....: [ 0.2554 + 0.3517*I, -0.4454 - 0.1715*I, 0.8325 - 0.6282*I]]) 

sage: G, M = A.gram_schmidt() 

sage: G.round(6) # random signs 

[-0.422243 - 0.490087*I 0.566698 - 0.097416*I -0.500882 + 0.002251*I] 

[-0.057002 - 0.495035*I -0.35059 - 0.625323*I 0.255514 - 0.415284*I] 

[ 0.394105 - 0.421778*I -0.392266 - 0.039345*I -0.352905 + 0.62195*I] 

sage: M.round(6) # random 

[ -1.528503 0.0 0.0] 

[ 0.459974 - 0.40061*I -1.741233 0.0] 

[-0.934304 + 0.148868*I 0.54833 + 0.073202*I -0.550725] 

sage: (A - M*G).zero_at(10^-12) 

[0.0 0.0 0.0] 

[0.0 0.0 0.0] 

[0.0 0.0 0.0] 

sage: (G*G.conjugate_transpose()) # random 

[0.9999999999999999 0.0 0.0] 

[ 0.0 0.9999999999999997 0.0] 

[ 0.0 0.0 1.0] 

  

A rectangular matrix. Note that the ``orthonormal`` keyword 

is ignored in these cases. :: 

  

sage: A = matrix(RDF, [[-0.978325, -0.751994, 0.925305, -0.200512, 0.420458], 

....: [-0.474877, -0.983403, 0.089836, 0.132218, 0.672965]]) 

sage: G, M = A.gram_schmidt(orthonormal=False) 

sage: G.round(6).zero_at(10^-6) 

[-0.607223 -0.466745 0.574315 -0.124453 0.260968] 

[ 0.123203 -0.617909 -0.530578 0.289773 0.487368] 

sage: M.round(6).zero_at(10^-6) 

[1.611147 0.0] 

[0.958116 0.867778] 

sage: (A-M*G).zero_at(10^-12) 

[0.0 0.0 0.0 0.0 0.0] 

[0.0 0.0 0.0 0.0 0.0] 

sage: (G*G.transpose()).round(6).zero_at(10^-6) 

[1.0 0.0] 

[0.0 1.0] 

  

Even though a set of vectors may be linearly dependent, no effort 

is made to decide when a zero vector is really the result of a 

relation of linear dependence. So in this regard, input matrices 

are treated as being of full rank. Try one of the base rings that 

provide exact results if you need exact results. :: 

  

sage: entries = [[1,1,2], [2,1,3], [3,1,4]] 

sage: A = matrix(QQ, entries) 

sage: A.rank() 

2 

sage: B = matrix(RDF, entries) 

sage: G, M = B.gram_schmidt() 

sage: G.round(6) # random signs 

[-0.408248 -0.408248 -0.816497] 

[ 0.707107 -0.707107 -0.0] 

[ -0.57735 -0.57735 0.57735] 

sage: M.round(10) # random 

[-2.4494897428 0.0 0.0] 

[-3.6742346142 0.7071067812 0.0] 

[-4.8989794856 1.4142135624 0.0] 

sage: (A - M*G).zero_at(1e-14) 

[0.0 0.0 0.0] 

[0.0 0.0 0.0] 

[0.0 0.0 0.0] 

sage: (G*G.transpose()) # abs tol 1e-14 

[0.9999999999999997 0.0 0.0] 

[ 0.0 0.9999999999999998 0.0] 

[ 0.0 0.0 1.0] 

  

Exact Rings, Orthonormalization: 

  

To scale a vector to unit length requires taking 

a square root, which often takes us outside the base ring. 

For the integers and the rationals, the field of algebraic numbers 

(``QQbar``) is big enough to contain what we need, but the price 

is that the computations are very slow, hence mostly of value 

for small cases or instruction. Now we need to use the 

``orthonormal`` keyword. :: 

  

sage: A = matrix(QQbar, [[6, -8, 1], 

....: [4, 1, 3], 

....: [6, 3, 3], 

....: [7, 1, -5], 

....: [7, -3, 5]]) 

sage: G, M = A.gram_schmidt(orthonormal=True) 

sage: G 

[ 0.5970223141259934? -0.7960297521679913? 0.09950371902099891?] 

[ 0.6063218341690895? 0.5289635311888953? 0.5937772444966257?] 

[ 0.5252981913594170? 0.2941669871612735? -0.798453250866314?] 

sage: M 

[ 10.04987562112089? 0 0] 

[ 1.890570661398980? 4.735582601355131? 0] 

[ 1.492555785314984? 7.006153332071100? 1.638930357041381?] 

[ 2.885607851608969? 1.804330147889395? 7.963520581008761?] 

[ 7.064764050490923? 5.626248468100069? -1.197679876299471?] 

sage: M*G-A 

[0 0 0] 

[0 0 0] 

[0 0 0] 

[0 0 0] 

[0 0 0] 

sage: (G*G.transpose()-identity_matrix(3)).norm() < 10^-10 

True 

sage: G.row_space() == A.row_space() 

True 

  

After :trac:`14047`, the matrix can also be over the algebraic reals 

``AA``:: 

  

sage: A = matrix(AA, [[6, -8, 1], 

....: [4, 1, 3], 

....: [6, 3, 3], 

....: [7, 1, -5], 

....: [7, -3, 5]]) 

sage: G, M = A.gram_schmidt(orthonormal=True) 

sage: G 

[ 0.5970223141259934? -0.7960297521679913? 0.09950371902099891?] 

[ 0.6063218341690895? 0.5289635311888953? 0.5937772444966257?] 

[ 0.5252981913594170? 0.2941669871612735? -0.798453250866314?] 

sage: M 

[ 10.04987562112089? 0 0] 

[ 1.890570661398980? 4.735582601355131? 0] 

[ 1.492555785314984? 7.006153332071100? 1.638930357041381?] 

[ 2.885607851608969? 1.804330147889395? 7.963520581008761?] 

[ 7.064764050490923? 5.626248468100069? -1.197679876299471?] 

  

Starting with complex numbers with rational real and imaginary parts. 

Note the use of the conjugate-transpose when checking the 

orthonormality. :: 

  

sage: A = matrix(QQbar, [[ -2, -I - 1, 4*I + 2, -1], 

....: [-4*I, -2*I + 17, 0, 9*I + 1], 

....: [ 1, -2*I - 6, -I + 11, -5*I + 1]]) 

sage: G, M = A.gram_schmidt(orthonormal=True) 

sage: (M*G-A).norm() < 10^-10 

True 

sage: id3 = G*G.conjugate().transpose() 

sage: (id3 - identity_matrix(3)).norm() < 10^-10 

True 

sage: G.row_space() == A.row_space() # long time 

True 

  

A square matrix with small rank. The zero vectors produced as a 

result of linear dependence get eliminated, so the rows of ``G`` 

are a basis for the row space of ``A``. :: 

  

sage: A = matrix(QQbar, [[2, -6, 3, 8], 

....: [1, -3, 2, 5], 

....: [0, 0, 2, 4], 

....: [2, -6, 3, 8]]) 

sage: A.change_ring(QQ).rank() 

2 

sage: G, M = A.gram_schmidt(orthonormal=True) 

sage: G 

[ 0.1881441736767195? -0.5644325210301583? 0.2822162605150792? 0.7525766947068779?] 

[-0.2502818123591464? 0.750845437077439? 0.3688363550555841? 0.4873908977520218?] 

sage: M 

[10.630145812734649? 0] 

[ 6.208757731331742? 0.6718090752798139?] 

[ 3.574739299857670? 2.687236301119256?] 

[10.630145812734649? 0] 

sage: M*G-A 

[0 0 0 0] 

[0 0 0 0] 

[0 0 0 0] 

[0 0 0 0] 

sage: (G*G.transpose()-identity_matrix(2)).norm() < 10^-10 

True 

sage: G.row_space() == A.row_space() 

True 

  

Exact Rings, Orthogonalization: 

  

If we forego scaling orthogonal vectors to unit vectors, we 

can apply Gram-Schmidt to a much greater variety of rings. 

Use the ``orthonormal=False`` keyword (or assume it as the default). 

Note that now the orthogonality check creates a diagonal matrix 

whose diagonal entries are the squares of the lengths of the 

vectors. 

  

First, in the rationals, without involving ``QQbar``. :: 

  

sage: A = matrix(QQ, [[-1, 3, 2, 2], 

....: [-1, 0, -1, 0], 

....: [-1, -2, -3, -1], 

....: [ 1, 1, 2, 0]]) 

sage: A.rank() 

3 

sage: G, M = A.gram_schmidt() 

sage: G 

[ -1 3 2 2] 

[-19/18 1/6 -8/9 1/9] 

[ 2/35 -4/35 -2/35 9/35] 

sage: M 

[ 1 0 0] 

[ -1/18 1 0] 

[-13/18 59/35 1] 

[ 1/3 -48/35 -2] 

sage: M*G-A 

[0 0 0 0] 

[0 0 0 0] 

[0 0 0 0] 

[0 0 0 0] 

sage: G*G.transpose() 

[ 18 0 0] 

[ 0 35/18 0] 

[ 0 0 3/35] 

sage: G.row_space() == A.row_space() 

True 

  

A complex subfield of the complex numbers. :: 

  

sage: C.<z> = CyclotomicField(5) 

sage: A = matrix(C, [[ -z^3 - 2*z, -z^3 - 1, 2*z^3 - 2*z^2 + 2*z, 1], 

....: [ z^3 - 2*z^2 + 1, -z^3 + 2*z^2 - z - 1, -1, z^2 + z], 

....: [-1/2*z^3 - 2*z^2 + z + 1, -z^3 + z - 2, -2*z^3 + 1/2*z^2, 2*z^2 - z + 2]]) 

sage: G, M = A.gram_schmidt(orthonormal=False) 

sage: G 

[ -z^3 - 2*z -z^3 - 1 2*z^3 - 2*z^2 + 2*z 1] 

[ 155/139*z^3 - 161/139*z^2 + 31/139*z + 13/139 -175/139*z^3 + 180/139*z^2 - 125/139*z - 142/139 230/139*z^3 + 124/139*z^2 + 6/139*z + 19/139 -14/139*z^3 + 92/139*z^2 - 6/139*z - 95/139] 

[-10359/19841*z^3 - 36739/39682*z^2 + 24961/39682*z - 11879/39682 -28209/39682*z^3 - 3671/19841*z^2 + 51549/39682*z - 38613/39682 -42769/39682*z^3 - 615/39682*z^2 - 1252/19841*z - 14392/19841 4895/19841*z^3 + 57885/39682*z^2 - 46094/19841*z + 65747/39682] 

sage: M 

[ 1 0 0] 

[ 14/139*z^3 + 47/139*z^2 + 145/139*z + 95/139 1 0] 

[ -7/278*z^3 + 199/278*z^2 + 183/139*z + 175/278 -3785/39682*z^3 + 3346/19841*z^2 - 3990/19841*z + 2039/19841 1] 

sage: M*G - A 

[0 0 0 0] 

[0 0 0 0] 

[0 0 0 0] 

sage: G*G.conjugate().transpose() 

[ 15*z^3 + 15*z^2 + 28 0 0] 

[ 0 463/139*z^3 + 463/139*z^2 + 1971/139 0] 

[ 0 0 230983/19841*z^3 + 230983/19841*z^2 + 1003433/39682] 

sage: G.row_space() == A.row_space() 

True 

  

A slightly edited legacy example. :: 

  

sage: A = matrix(ZZ, 3, [-1, 2, 5, -11, 1, 1, 1, -1, -3]); A 

[ -1 2 5] 

[-11 1 1] 

[ 1 -1 -3] 

sage: G, mu = A.gram_schmidt() 

sage: G 

[ -1 2 5] 

[ -52/5 -1/5 -2] 

[ 2/187 36/187 -14/187] 

sage: mu 

[ 1 0 0] 

[ 3/5 1 0] 

[ -3/5 -7/187 1] 

sage: G.row(0) * G.row(1) 

0 

sage: G.row(0) * G.row(2) 

0 

sage: G.row(1) * G.row(2) 

0 

  

The relation between mu and A is as follows. :: 

  

sage: mu*G == A 

True 

""" 

import sage.rings.real_double 

import sage.rings.complex_double 

R = self.base_ring() 

if R in [sage.rings.real_double.RDF, sage.rings.complex_double.CDF]: 

Q, R = self.transpose().QR() 

m = R.nrows(); n = R.ncols() 

if m > n: 

Q = Q[0:m, 0:n] 

R = R[0:n, 0:n] 

elif R.is_exact(): 

if self == 1: 

# this special case occurs frequently enough to deserve a shortcut 

return (self, self) 

  

if orthonormal: 

Q, R = self.transpose().QR(full=False) 

else: 

Q, R = self.transpose()._gram_schmidt_noscale() 

else: 

raise NotImplementedError("Gram-Schmidt orthogonalization not implemented for matrices over inexact rings, except for RDF and CDF") 

return Q.transpose(), R.transpose() 

  

def jordan_form(self, base_ring=None, sparse=False, subdivide=True, transformation=False, eigenvalues=None, check_input=True): 

r""" 

Compute the Jordan normal form of this square matrix `A`, if it exists. 

  

This computation is performed in a naive way using the ranks of powers 

of `A-xI`, where `x` is an eigenvalue of the matrix `A`. If desired, 

a transformation matrix `P` can be returned, which is such that the 

Jordan canonical form is given by `P^{-1} A P`; if the matrix is 

diagonalizable, this equals to *eigendecomposition* or *spectral 

decomposition*. 

  

INPUT: 

  

- ``base_ring`` - Ring in which to compute the Jordan form. 

  

- ``sparse`` - (default ``False``) If ``sparse=True``, return a sparse 

matrix. 

  

- ``subdivide`` - (default ``True``) If ``subdivide=True``, the 

subdivisions for the Jordan blocks in the matrix are shown. 

  

- ``transformation`` - (default ``False``) If ``transformation=True``, 

computes also the transformation matrix. 

  

- ``eigenvalues`` - (default ``None``) A complete set of roots, with 

multiplicity, of the characteristic polynomial of `A`, encoded as 

a list of pairs, each having the form `(r, m)` with `r` a root and 

`m` its multiplicity. If this is ``None``, then Sage computes this 

list itself, but this is only possible over base rings in whose 

quotient fields polynomial factorization is implemented. Over all 

other rings, providing this list manually is the only way to 

compute Jordan normal forms. 

  

- ``check_input`` - (default ``True``) A Boolean specifying whether 

the list ``eigenvalues`` (if provided) has to be checked for 

correctness. Set this to ``False`` for a speedup if the eigenvalues 

are known to be correct. 

  

NOTES: 

  

Currently, the Jordan normal form is not computed over inexact rings 

in any but the trivial cases when the matrix is either `0 \times 0` 

or `1 \times 1`. 

  

In the case of exact rings, this method does not compute any 

generalized form of the Jordan normal form, but is only able to 

compute the result if the characteristic polynomial of the matrix 

splits over the specific base ring. 

  

Note that the base ring must be a field or a ring with an implemented 

fraction field. 

  

EXAMPLES:: 

  

sage: a = matrix(ZZ,4,[1, 0, 0, 0, 0, 1, 0, 0, 1, \ 

-1, 1, 0, 1, -1, 1, 2]); a 

[ 1 0 0 0] 

[ 0 1 0 0] 

[ 1 -1 1 0] 

[ 1 -1 1 2] 

sage: a.jordan_form() 

[2|0 0|0] 

[-+---+-] 

[0|1 1|0] 

[0|0 1|0] 

[-+---+-] 

[0|0 0|1] 

sage: a.jordan_form(subdivide=False) 

[2 0 0 0] 

[0 1 1 0] 

[0 0 1 0] 

[0 0 0 1] 

sage: b = matrix(ZZ,3,3,range(9)); b 

[0 1 2] 

[3 4 5] 

[6 7 8] 

sage: b.jordan_form() 

Traceback (most recent call last): 

... 

RuntimeError: Some eigenvalue does not exist in Rational Field. 

sage: b.jordan_form(RealField(15)) 

Traceback (most recent call last): 

... 

ValueError: Jordan normal form not implemented over inexact rings. 

  

Here we need to specify a field, since the eigenvalues are not defined 

in the smallest ring containing the matrix entries (:trac:`14508`):: 

  

sage: c = matrix([[0,1,0],[0,0,1],[1,0,0]]); 

sage: c.jordan_form(CyclotomicField(3)) 

[ 1| 0| 0] 

[----------+----------+----------] 

[ 0| zeta3| 0] 

[----------+----------+----------] 

[ 0| 0|-zeta3 - 1] 

  

If you need the transformation matrix as well as the Jordan form of 

``self``, then pass the option ``transformation=True``. For example:: 

  

sage: m = matrix([[5,4,2,1],[0,1,-1,-1],[-1,-1,3,0],[1,1,-1,2]]); m 

[ 5 4 2 1] 

[ 0 1 -1 -1] 

[-1 -1 3 0] 

[ 1 1 -1 2] 

sage: jf, p = m.jordan_form(transformation=True) 

sage: jf 

[2|0|0 0] 

[-+-+---] 

[0|1|0 0] 

[-+-+---] 

[0|0|4 1] 

[0|0|0 4] 

sage: ~p * m * p 

[2 0 0 0] 

[0 1 0 0] 

[0 0 4 1] 

[0 0 0 4] 

  

Note that for matrices over inexact rings, we do not attempt to 

compute the Jordan normal form, since it is not numerically 

stable:: 

  

sage: b = matrix(ZZ,3,3,range(9)) 

sage: jf, p = b.jordan_form(RealField(15), transformation=True) 

Traceback (most recent call last): 

... 

ValueError: Jordan normal form not implemented over inexact rings. 

  

TESTS:: 

  

sage: c = matrix(ZZ, 3, [1]*9); c 

[1 1 1] 

[1 1 1] 

[1 1 1] 

sage: c.jordan_form(subdivide=False) 

[3 0 0] 

[0 0 0] 

[0 0 0] 

  

:: 

  

sage: evals = [(i,i) for i in range(1,6)] 

sage: n = sum(range(1,6)) 

sage: jf = block_diagonal_matrix([jordan_block(ev,size) for ev,size in evals]) 

sage: p = random_matrix(ZZ,n,n) 

sage: while p.rank() != n: p = random_matrix(ZZ,n,n) 

sage: m = p * jf * ~p 

sage: mjf, mp = m.jordan_form(transformation=True) 

sage: mjf == jf 

True 

sage: m = diagonal_matrix([1,1,0,0]) 

sage: jf,P = m.jordan_form(transformation=True) 

sage: jf == ~P*m*P 

True 

  

We verify that the bug from :trac:`6942` is fixed:: 

  

sage: M = Matrix(GF(2),[[1,0,1,0,0,0,1],[1,0,0,1,1,1,0],[1,1,0,1,1,1,1],[1,1,1,0,1,1,1],[1,1,1,0,0,1,0],[1,1,1,0,1,0,0],[1,1,1,1,1,1,0]]) 

sage: J, T = M.jordan_form(transformation=True) 

sage: J 

[1 1|0 0|0 0|0] 

[0 1|0 0|0 0|0] 

[---+---+---+-] 

[0 0|1 1|0 0|0] 

[0 0|0 1|0 0|0] 

[---+---+---+-] 

[0 0|0 0|1 1|0] 

[0 0|0 0|0 1|0] 

[---+---+---+-] 

[0 0|0 0|0 0|1] 

sage: M * T == T * J 

True 

sage: T.rank() 

7 

sage: M.rank() 

7 

  

We verify that the bug from :trac:`6932` is fixed:: 

  

sage: M=Matrix(1,1,[1]) 

sage: M.jordan_form(transformation=True) 

([1], [1]) 

  

We now go through three `10 \times 10` matrices to exhibit cases where 

there are multiple blocks of the same size:: 

  

sage: A = matrix(QQ, [[15, 37/3, -16, -104/3, -29, -7/3, 0, 2/3, -29/3, -1/3], [2, 9, -1, -6, -6, 0, 0, 0, -2, 0], [24, 74/3, -41, -208/3, -58, -23/3, 0, 4/3, -58/3, -2/3], [-6, -19, 3, 21, 19, 0, 0, 0, 6, 0], [2, 6, 3, -6, -3, 1, 0, 0, -2, 0], [-96, -296/3, 176, 832/3, 232, 101/3, 0, -16/3, 232/3, 8/3], [-4, -2/3, 21, 16/3, 4, 14/3, 3, -1/3, 4/3, -25/3], [20, 26/3, -66, -199/3, -42, -41/3, 0, 13/3, -55/3, -2/3], [18, 57, -9, -54, -57, 0, 0, 0, -15, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]]); A 

[ 15 37/3 -16 -104/3 -29 -7/3 0 2/3 -29/3 -1/3] 

[ 2 9 -1 -6 -6 0 0 0 -2 0] 

[ 24 74/3 -41 -208/3 -58 -23/3 0 4/3 -58/3 -2/3] 

[ -6 -19 3 21 19 0 0 0 6 0] 

[ 2 6 3 -6 -3 1 0 0 -2 0] 

[ -96 -296/3 176 832/3 232 101/3 0 -16/3 232/3 8/3] 

[ -4 -2/3 21 16/3 4 14/3 3 -1/3 4/3 -25/3] 

[ 20 26/3 -66 -199/3 -42 -41/3 0 13/3 -55/3 -2/3] 

[ 18 57 -9 -54 -57 0 0 0 -15 0] 

[ 0 0 0 0 0 0 0 0 0 3] 

sage: J, T = A.jordan_form(transformation=True); J 

[3 1 0|0 0 0|0 0 0|0] 

[0 3 1|0 0 0|0 0 0|0] 

[0 0 3|0 0 0|0 0 0|0] 

[-----+-----+-----+-] 

[0 0 0|3 1 0|0 0 0|0] 

[0 0 0|0 3 1|0 0 0|0] 

[0 0 0|0 0 3|0 0 0|0] 

[-----+-----+-----+-] 

[0 0 0|0 0 0|3 1 0|0] 

[0 0 0|0 0 0|0 3 1|0] 

[0 0 0|0 0 0|0 0 3|0] 

[-----+-----+-----+-] 

[0 0 0|0 0 0|0 0 0|3] 

sage: T * J * T**(-1) == A 

True 

sage: T.rank() 

10 

  

:: 

  

sage: A = matrix(QQ, [[15, 37/3, -16, -14/3, -29, -7/3, 0, 2/3, 1/3, 44/3], [2, 9, -1, 0, -6, 0, 0, 0, 0, 3], [24, 74/3, -41, -28/3, -58, -23/3, 0, 4/3, 2/3, 88/3], [-6, -19, 3, 3, 19, 0, 0, 0, 0, -9], [2, 6, 3, 0, -3, 1, 0, 0, 0, 3], [-96, -296/3, 176, 112/3, 232, 101/3, 0, -16/3, -8/3, -352/3], [-4, -2/3, 21, 16/3, 4, 14/3, 3, -1/3, 4/3, -25/3], [20, 26/3, -66, -28/3, -42, -41/3, 0, 13/3, 2/3, 82/3], [18, 57, -9, 0, -57, 0, 0, 0, 3, 28], [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]]); A 

[ 15 37/3 -16 -14/3 -29 -7/3 0 2/3 1/3 44/3] 

[ 2 9 -1 0 -6 0 0 0 0 3] 

[ 24 74/3 -41 -28/3 -58 -23/3 0 4/3 2/3 88/3] 

[ -6 -19 3 3 19 0 0 0 0 -9] 

[ 2 6 3 0 -3 1 0 0 0 3] 

[ -96 -296/3 176 112/3 232 101/3 0 -16/3 -8/3 -352/3] 

[ -4 -2/3 21 16/3 4 14/3 3 -1/3 4/3 -25/3] 

[ 20 26/3 -66 -28/3 -42 -41/3 0 13/3 2/3 82/3] 

[ 18 57 -9 0 -57 0 0 0 3 28] 

[ 0 0 0 0 0 0 0 0 0 3] 

sage: J, T = A.jordan_form(transformation=True); J 

[3 1 0|0 0 0|0 0|0 0] 

[0 3 1|0 0 0|0 0|0 0] 

[0 0 3|0 0 0|0 0|0 0] 

[-----+-----+---+---] 

[0 0 0|3 1 0|0 0|0 0] 

[0 0 0|0 3 1|0 0|0 0] 

[0 0 0|0 0 3|0 0|0 0] 

[-----+-----+---+---] 

[0 0 0|0 0 0|3 1|0 0] 

[0 0 0|0 0 0|0 3|0 0] 

[-----+-----+---+---] 

[0 0 0|0 0 0|0 0|3 1] 

[0 0 0|0 0 0|0 0|0 3] 

sage: T * J * T**(-1) == A 

True 

sage: T.rank() 

10 

  

:: 

  

sage: A = matrix(QQ, [[15, 37/3, -16, -104/3, -29, -7/3, 35, 2/3, -29/3, -1/3], [2, 9, -1, -6, -6, 0, 7, 0, -2, 0], [24, 74/3, -29, -208/3, -58, -14/3, 70, 4/3, -58/3, -2/3], [-6, -19, 3, 21, 19, 0, -21, 0, 6, 0], [2, 6, -1, -6, -3, 0, 7, 0, -2, 0], [-96, -296/3, 128, 832/3, 232, 65/3, -279, -16/3, 232/3, 8/3], [0, 0, 0, 0, 0, 0, 3, 0, 0, 0], [20, 26/3, -30, -199/3, -42, -14/3, 70, 13/3, -55/3, -2/3], [18, 57, -9, -54, -57, 0, 63, 0, -15, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]]); A 

[ 15 37/3 -16 -104/3 -29 -7/3 35 2/3 -29/3 -1/3] 

[ 2 9 -1 -6 -6 0 7 0 -2 0] 

[ 24 74/3 -29 -208/3 -58 -14/3 70 4/3 -58/3 -2/3] 

[ -6 -19 3 21 19 0 -21 0 6 0] 

[ 2 6 -1 -6 -3 0 7 0 -2 0] 

[ -96 -296/3 128 832/3 232 65/3 -279 -16/3 232/3 8/3] 

[ 0 0 0 0 0 0 3 0 0 0] 

[ 20 26/3 -30 -199/3 -42 -14/3 70 13/3 -55/3 -2/3] 

[ 18 57 -9 -54 -57 0 63 0 -15 0] 

[ 0 0 0 0 0 0 0 0 0 3] 

sage: J, T = A.jordan_form(transformation=True); J 

[3 1 0|0 0|0 0|0 0|0] 

[0 3 1|0 0|0 0|0 0|0] 

[0 0 3|0 0|0 0|0 0|0] 

[-----+---+---+---+-] 

[0 0 0|3 1|0 0|0 0|0] 

[0 0 0|0 3|0 0|0 0|0] 

[-----+---+---+---+-] 

[0 0 0|0 0|3 1|0 0|0] 

[0 0 0|0 0|0 3|0 0|0] 

[-----+---+---+---+-] 

[0 0 0|0 0|0 0|3 1|0] 

[0 0 0|0 0|0 0|0 3|0] 

[-----+---+---+---+-] 

[0 0 0|0 0|0 0|0 0|3] 

sage: T * J * T**(-1) == A 

True 

sage: T.rank() 

10 

  

Verify that we smoothly move to QQ from ZZ (:trac:`12693`), i.e. 

we work in the vector space over the field:: 

  

sage: M = matrix(((2,2,2),(0,0,0),(-2,-2,-2))) 

sage: J, P = M.jordan_form(transformation=True) 

sage: J; P 

[0 1|0] 

[0 0|0] 

[---+-] 

[0 0|0] 

[ 2 1 0] 

[ 0 0 1] 

[-2 0 -1] 

sage: J - ~P * M * P 

[0 0 0] 

[0 0 0] 

[0 0 0] 

sage: parent(M) 

Full MatrixSpace of 3 by 3 dense matrices over Integer Ring 

sage: parent(J) == parent(P) == MatrixSpace(QQ, 3) 

True 

sage: M.jordan_form(transformation=True) == (M/1).jordan_form(transformation=True) 

True 

  

By providing eigenvalues ourselves, we can compute the Jordan form even 

lacking a polynomial factorization algorithm. :: 

  

sage: Qx = PolynomialRing(QQ, 'x11, x12, x13, x21, x22, x23, x31, x32, x33') 

sage: x11, x12, x13, x21, x22, x23, x31, x32, x33 = Qx.gens() 

sage: M = matrix(Qx, [[0, 0, x31], [0, 0, x21], [0, 0, 0]]) # This is a nilpotent matrix. 

sage: M.jordan_form(eigenvalues=[(0, 3)]) 

[0 1|0] 

[0 0|0] 

[---+-] 

[0 0|0] 

sage: M.jordan_form(eigenvalues=[(0, 2)]) 

Traceback (most recent call last): 

... 

ValueError: The provided list of eigenvalues is not correct. 

sage: M.jordan_form(transformation=True, eigenvalues=[(0, 3)]) 

( 

[0 1|0] 

[0 0|0] [x31 0 1] 

[---+-] [x21 0 0] 

[0 0|0], [ 0 1 0] 

) 

  

The base ring for the matrix needs to have a fraction field 

and it needs to be implemented. :: 

  

sage: A = matrix(Integers(6), 2, 2, range(4)) 

sage: A.jordan_form() 

Traceback (most recent call last): 

... 

ValueError: Matrix entries must be from a field, not Ring of integers modulo 6 

""" 

from sage.matrix.constructor import block_diagonal_matrix, jordan_block, diagonal_matrix 

from sage.combinat.partition import Partition 

  

if self.ncols() != self.nrows(): 

raise ValueError("Jordan normal form not implemented for non-square matrices.") 

  

# Set ``n`` to the number of rows and handle trivial cases, regardless 

# of the underlying ring. 

n = self.nrows() 

if n == 0: 

if not transformation: 

return self 

else: 

return self, self 

elif n == 1: 

if not transformation: 

return self 

else: 

return self, self.parent().identity_matrix() 

  

inferred_base_ring = base_ring 

  

if base_ring is None: 

inferred_base_ring = self.base_ring() 

  

if not inferred_base_ring.is_exact(): 

raise ValueError("Jordan normal form not implemented over inexact rings.") 

  

# Make sure we're working with a field. 

if inferred_base_ring.is_field(): 

if base_ring is not None: 

A = self.change_ring(inferred_base_ring) 

else: 

A = self 

else: 

try: 

base_field = inferred_base_ring.fraction_field() 

except (NotImplementedError, TypeError, AttributeError): 

raise ValueError("Matrix entries must be from a field, not {0}". 

format(inferred_base_ring)) 

A = self.change_ring(base_field) 

  

# Compute the eigenvalues of the matrix, with multiplicities. Here, 

# ``evals`` is a list of pairs, each first entry a root and each 

# second entry the corresponding multiplicity. 

if eigenvalues is not None: 

if check_input: # Checking input for sanity. 

C1 = A.charpoly() 

Polyring = C1.parent() 

C2 = Polyring.one() 

x = Polyring.gens()[0] 

for z, i in eigenvalues: 

C2 *= (x - z) ** i 

if C1 != C2: 

raise ValueError("The provided list of eigenvalues is not correct.") 

evals = eigenvalues 

else: 

evals = A.charpoly().roots() 

if sum([mult for (_,mult) in evals]) < n: 

raise RuntimeError("Some eigenvalue does not exist in %s." %(A.base_ring())) 

  

# Compute the block information. Here, ``blocks`` is a list of pairs, 

# each first entry a root and each second entry the size of a block. 

# Note that in general there is more than one block per eigenvalue! 

blocks = [] 

for eval, mult in evals: 

if mult == 1: 

blocks.append((eval,1)) 

else: 

B = A - diagonal_matrix([eval]*n, sparse=sparse) 

C = B 

ranks = [n, C.rank()] 

i = 0 

while ranks[i] > ranks[i+1] and ranks[i+1] > n-mult: 

C = B*C 

ranks.append(C.rank()) 

i = i+1 

diagram = [ranks[i]-ranks[i+1] for i in xrange(len(ranks)-1)] 

blocks.extend([(eval, i) \ 

for i in Partition(diagram).conjugate()]) 

  

# ``J`` is the matrix in Jordan canonical form. Note that the blocks 

# are ordered firstly by the eigenvalues, in the same order as obeyed 

# by ``.roots()``, and secondly by size from greatest to smallest. 

J = block_diagonal_matrix([jordan_block(eval, size, sparse=sparse) \ 

for (eval, size) in blocks], subdivide=subdivide) 

  

if transformation: 

from itertools import groupby 

  

# ``jordan_chains`` is a dictionary with keys the eigenvalues. 

# For every eigenvalue, we consider all Jordan blocks and find 

# a Jordan chain for each, adding the chain (a sequence of 

# vectors) to the entry for the eigenvalue (which is a list). 

jordan_chains = {} 

for eval,_ in evals: 

jordan_chains[eval] = [] 

  

# Let B be the matrix `A - eval Id`. 

B = A - eval 

  

block_sizes = [size for e,size in blocks if e == eval] 

block_size_pairs = [(val,len(list(c))) \ 

for val,c in groupby(block_sizes)] 

  

# Y is a list of vectors, spanning everything that we have 

# covered by the Jordan chains we developed so far. 

Y = [] 

  

for l,count in block_size_pairs: 

  

# There are ``count`` Jordan blocks of size ``l`` 

# associated to this eigenvalue. 

  

# We want to find elements in `\ker B^l - \ker B^{l-1}`. 

Vlarge = (B**l).right_kernel().basis() 

Vsmall = (B**(l-1)).right_kernel().basis() 

  

for i in range(count): 

# Let v be any vector in `\ker B^l` not in the kernel 

# of `\ker B^{l-1}` which is also not in the span(Y), 

# and start a chain from there. 

v = _jordan_form_vector_in_difference(Vlarge, Vsmall+Y) 

chain = [v] 

for i in range(l-1): 

chain.append(B*chain[-1]) 

chain.reverse() 

Y.extend(chain) 

jordan_chains[eval].append(chain) 

  

# Now ``jordan_chains`` has all the columns of the transformation 

# matrix; we just need to put them in the right order. 

jordan_basis = [] 

for eval,size in blocks: 

# Find a block with the right size 

for index,chain in enumerate(jordan_chains[eval]): 

if len(chain)==size: 

jordan_basis += jordan_chains[eval].pop(index) 

break 

  

transformation_matrix = (A.parent()(jordan_basis)).transpose() 

  

if transformation: 

return J, transformation_matrix 

else: 

return J 

  

def is_diagonalizable(self, base_field=None): 

r""" 

Determines if the matrix is similar to a diagonal matrix. 

  

INPUT: 

  

- ``base_field`` - a new field to use for entries 

of the matrix. 

  

OUTPUT: 

  

If ``self`` is the matrix `A`, then it is diagonalizable 

if there is an invertible matrix `S` and a diagonal matrix 

`D` such that 

  

.. MATH:: 

  

S^{-1}AS = D 

  

This routine returns ``True`` if ``self`` is diagonalizable. 

The diagonal entries of the matrix `D` are the eigenvalues 

of `A`. It may be necessary to "increase" the base field to 

contain all of the eigenvalues. Over the rationals, the field 

of algebraic numbers, :mod:`sage.rings.qqbar` is a good choice. 

  

To obtain the matrices `S` and `D` use the :meth:`jordan_form` 

method with the ``transformation=True`` keyword. 

  

ALGORITHM: 

  

For each eigenvalue, this routine checks that the algebraic 

multiplicity (number of occurrences as a root of the characteristic 

polynomial) is equal to the geometric multiplicity (dimension 

of the eigenspace), which is sufficient to ensure a basis of 

eigenvectors for the columns of `S`. 

  

EXAMPLES: 

  

A matrix that is diagonalizable over the rationals, as evidenced 

by its Jordan form. :: 

  

sage: A = matrix(QQ, [[-7, 16, 12, 0, 6], 

....: [-9, 15, 0, 12, -27], 

....: [ 9, -8, 11, -12, 51], 

....: [ 3, -4, 0, -1, 9], 

....: [-1, 0, -4, 4, -12]]) 

sage: A.jordan_form(subdivide=False) 

[ 2 0 0 0 0] 

[ 0 3 0 0 0] 

[ 0 0 3 0 0] 

[ 0 0 0 -1 0] 

[ 0 0 0 0 -1] 

sage: A.is_diagonalizable() 

True 

  

A matrix that is not diagonalizable over the rationals, as evidenced 

by its Jordan form. :: 

  

sage: A = matrix(QQ, [[-3, -14, 2, -1, 15], 

....: [4, 6, -2, 3, -8], 

....: [-2, -14, 0, 0, 10], 

....: [3, 13, -2, 0, -11], 

....: [-1, 6, 1, -3, 1]]) 

sage: A.jordan_form(subdivide=False) 

[-1 1 0 0 0] 

[ 0 -1 0 0 0] 

[ 0 0 2 1 0] 

[ 0 0 0 2 1] 

[ 0 0 0 0 2] 

sage: A.is_diagonalizable() 

False 

  

If any eigenvalue of a matrix is outside the base ring, then 

this routine raises an error. However, the ring can be 

"expanded" to contain the eigenvalues. :: 

  

sage: A = matrix(QQ, [[1, 0, 1, 1, -1], 

....: [0, 1, 0, 4, 8], 

....: [2, 1, 3, 5, 1], 

....: [2, -1, 1, 0, -2], 

....: [0, -1, -1, -5, -8]]) 

  

sage: [e in QQ for e in A.eigenvalues()] 

[False, False, False, False, False] 

sage: A.is_diagonalizable() 

Traceback (most recent call last): 

... 

RuntimeError: an eigenvalue of the matrix is not contained in Rational Field 

  

sage: [e in QQbar for e in A.eigenvalues()] 

[True, True, True, True, True] 

sage: A.is_diagonalizable(base_field=QQbar) 

True 

  

Other exact fields may be employed, though it will not always 

be possible to expand their base fields to contain all 

the eigenvalues. :: 

  

sage: F.<b> = FiniteField(5^2) 

sage: A = matrix(F, [[ 4, 3*b + 2, 3*b + 1, 3*b + 4], 

....: [2*b + 1, 4*b, 0, 2], 

....: [ 4*b, b + 2, 2*b + 3, 3], 

....: [ 2*b, 3*b, 4*b + 4, 3*b + 3]]) 

sage: A.jordan_form() 

[ 4 1| 0 0] 

[ 0 4| 0 0] 

[---------------+---------------] 

[ 0 0|2*b + 1 1] 

[ 0 0| 0 2*b + 1] 

sage: A.is_diagonalizable() 

False 

  

sage: F.<c> = QuadraticField(-7) 

sage: A = matrix(F, [[ c + 3, 2*c - 2, -2*c + 2, c - 1], 

....: [2*c + 10, 13*c + 15, -13*c - 17, 11*c + 31], 

....: [2*c + 10, 14*c + 10, -14*c - 12, 12*c + 30], 

....: [ 0, 2*c - 2, -2*c + 2, 2*c + 2]]) 

sage: A.jordan_form(subdivide=False) 

[ 4 0 0 0] 

[ 0 -2 0 0] 

[ 0 0 c + 3 0] 

[ 0 0 0 c + 3] 

sage: A.is_diagonalizable() 

True 

  

A trivial matrix is diagonalizable, trivially. :: 

  

sage: A = matrix(QQ, 0, 0) 

sage: A.is_diagonalizable() 

True 

  

A matrix must be square to be diagonalizable. :: 

  

sage: A = matrix(QQ, 3, 4) 

sage: A.is_diagonalizable() 

False 

  

The matrix must have entries from a field, 

and it must be an exact field. :: 

  

sage: A = matrix(ZZ, 4, range(16)) 

sage: A.is_diagonalizable() 

Traceback (most recent call last): 

... 

ValueError: matrix entries must be from a field, not Integer Ring 

  

sage: A = matrix(RDF, 4, range(16)) 

sage: A.is_diagonalizable() 

Traceback (most recent call last): 

... 

ValueError: base field must be exact, not Real Double Field 

  

AUTHOR: 

  

- Rob Beezer (2011-04-01) 

""" 

if not self.is_square(): 

return False 

if not base_field is None: 

self = self.change_ring(base_field) 

if not self.base_ring().is_exact(): 

raise ValueError('base field must be exact, not {0}'.format(self.base_ring())) 

if not self.base_ring().is_field(): 

raise ValueError('matrix entries must be from a field, not {0}'.format(self.base_ring())) 

  

evals = self.charpoly().roots() 

if sum([mult for (_,mult) in evals]) < self._nrows: 

raise RuntimeError('an eigenvalue of the matrix is not contained in {0}'.format(self.base_ring())) 

  

# Obtaining a generic minimal polynomial requires much more 

# computation with kernels and their dimensions than the following. 

# However, if a derived class has a fast minimal polynomial routine 

# then overriding this by checking for repeated factors might be faster. 

  

# check equality of algebraic multiplicity and geometric multiplicity 

for e, am in evals: 

gm = (self - e).right_kernel().dimension() 

if am != gm: 

return False 

return True 

  

def is_similar(self, other, transformation=False): 

r""" 

Return ``True`` if ``self`` and ``other`` are similar, 

i.e. related by a change-of-basis matrix. 

  

INPUT: 

  

- ``other`` -- a matrix, which should be square, and of the same size 

as ``self``. 

  

- ``transformation`` -- default: ``False`` - if ``True``, the output 

may include the change-of-basis matrix (also known as the similarity 

transformation). See below for an exact description. 

  

OUTPUT: 

  

Two matrices, `A` and `B` are similar if they are square 

matrices of the same size and there is an invertible matrix 

`S` such that `A=S^{-1}BS`. `S` can be interpreted as a 

change-of-basis matrix if `A` and `B` are viewed as matrix 

representations of the same linear transformation from a vector space 

to itself. 

  

When ``transformation=False`` this method will return ``True`` if 

such a matrix `S` exists, otherwise it will return ``False``. When 

``transformation=True`` the method returns a pair. The first part 

of the pair is ``True`` or ``False`` depending on if the matrices 

are similar. The second part of the pair is the change-of-basis 

matrix when the matrices are similar and ``None`` when the matrices 

are not similar. 

  

When a similarity transformation matrix ``S`` is requested, 

it will satisfy ``self = S.inverse()*other*S``. 

  

.. RUBRIC:: rings and coefficients 

  

Inexact rings are not supported. Only rings having a 

fraction field can be used as coefficients. 

  

The base rings for the matrices are promoted to a common 

field for the similarity check using rational form over this field. 

  

If the fraction fields of both matrices are the same, this 

field is used. Otherwise, if the fraction fields are only 

related by a canonical coercion, the common coercion field 

is used. 

  

In all cases, the result is about similarity over a common field. 

  

.. RUBRIC:: similarity transformation 

  

For computation of the similarity transformation, the 

matrices are first checked to be similar over their common 

field. 

  

In this case, a similarity transformation is then 

searched for over the common field. If this fails, the 

matrices are promoted to the algebraic closure of their 

common field (whenever it is available) and a similarity 

transformation is looked for over the algebraic closure. 

  

For example, matrices over the rationals 

may be promoted to the field of algebraic numbers (``QQbar``) 

for computation of the similarity transformation. 

  

.. WARNING:: 

  

When the two matrices are similar, this routine may 

fail to find the similarity transformation. A technical 

explanation follows. 

  

The similarity check is accomplished with rational form, which 

will be successful for any pair of matrices over the same field. 

However, the computation of rational form does not provide a 

transformation. So we instead compute Jordan form, which does 

provide a transformation. But Jordan form will require that 

the eigenvalues of the matrix can be represented within Sage, 

requiring the existence of the appropriate extension field. 

When this is not possible, a ``RuntimeError`` is raised, as 

demonstrated in an example below. 

  

EXAMPLES: 

  

The two matrices in this example were constructed to be similar. 

The computations happen in the field of algebraic numbers, but we 

are able to convert the change-of-basis matrix back to the rationals 

(which may not always be possible). :: 

  

sage: A = matrix(ZZ, [[-5, 2, -11], 

....: [-6, 7, -42], 

....: [0, 1, -6]]) 

sage: B = matrix(ZZ, [[ 1, 12, 3], 

....: [-1, -6, -1], 

....: [ 0, 6, 1]]) 

sage: A.is_similar(B) 

True 

sage: _, T = A.is_similar(B, transformation=True) 

sage: T 

[ 1.00000000000000? + 0.?e-14*I 0.?e-14 + 0.?e-14*I 0.?e-14 + 0.?e-14*I] 

[-0.66666666666667? + 0.?e-15*I 0.166666666666667? + 0.?e-15*I -0.83333333333334? + 0.?e-14*I] 

[ 0.66666666666667? + 0.?e-14*I 0.?e-14 + 0.?e-14*I -0.33333333333333? + 0.?e-14*I] 

sage: T.change_ring(QQ) 

[ 1 0 0] 

[-2/3 1/6 -5/6] 

[ 2/3 0 -1/3] 

sage: A == T.inverse()*B*T 

True 

  

Other exact fields are supported. :: 

  

sage: F.<a> = FiniteField(7^2) 

sage: A = matrix(F,[[2*a + 5, 6*a + 6, a + 3], 

....: [ a + 3, 2*a + 2, 4*a + 2], 

....: [2*a + 6, 5*a + 5, 3*a]]) 

sage: B = matrix(F,[[5*a + 5, 6*a + 4, a + 1], 

....: [ a + 5, 4*a + 3, 3*a + 3], 

....: [3*a + 5, a + 4, 5*a + 6]]) 

sage: A.is_similar(B) 

True 

sage: B.is_similar(A) 

True 

sage: _, T = A.is_similar(B, transformation=True) 

sage: T 

[ 1 0 0] 

[6*a + 1 4*a + 3 4*a + 2] 

[6*a + 3 3*a + 5 3*a + 6] 

sage: A == T.inverse()*B*T 

True 

  

Two matrices with different sets of eigenvalues, so they 

cannot possibly be similar. :: 

  

sage: A = matrix(QQ, [[ 2, 3, -3, -6], 

....: [ 0, 1, -2, -8], 

....: [-3, -3, 4, 3], 

....: [-1, -2, 2, 6]]) 

sage: B = matrix(QQ, [[ 1, 1, 2, 4], 

....: [-1, 2, -3, -7], 

....: [-2, 3, -4, -7], 

....: [ 0, -1, 0, 0]]) 

sage: A.eigenvalues() == B.eigenvalues() 

False 

sage: A.is_similar(B, transformation=True) 

(False, None) 

  

Similarity is an equivalence relation, so this routine computes 

a representative of the equivalence class for each matrix, the 

rational form, as provided by :meth:`rational_form`. The matrices 

below have identical eigenvalues (as evidenced by equal 

characteristic polynomials), but slightly different rational forms, 

and hence are not similar. :: 

  

sage: A = matrix(QQ, [[ 19, -7, -29], 

....: [-16, 11, 30], 

....: [ 15, -7, -25]]) 

sage: B = matrix(QQ, [[-38, -63, 42], 

....: [ 14, 25, -14], 

....: [-14, -21, 18]]) 

sage: A.charpoly() == B.charpoly() 

True 

sage: A.rational_form() 

[ 0 0 -48] 

[ 1 0 8] 

[ 0 1 5] 

sage: B.rational_form() 

[ 4| 0 0] 

[--+-----] 

[ 0| 0 12] 

[ 0| 1 1] 

sage: A.is_similar(B) 

False 

  

Obtaining the transformation between two similar matrices 

requires the Jordan form, which requires computing the 

eigenvalues of the matrix, which may not lie in the field 

used for entries of the matrix. In this unfortunate case, 

the computation of the transformation may fail with a 

``RuntimeError``, EVEN when the matrices are similar. This 

is not the case for matrices over the integers, rationals 

or algebraic numbers, since the computations are done in 

the algebraically closed field of algebraic numbers. 

Here is an example where the similarity is obvious by 

design, but we are not able to resurrect a similarity 

transformation. :: 

  

sage: F.<a> = FiniteField(7^2) 

sage: C = matrix(F,[[ a + 2, 5*a + 4], 

....: [6*a + 6, 6*a + 4]]) 

sage: S = matrix(F, [[0, 1], 

....: [1, 0]]) 

sage: D = S.inverse()*C*S 

sage: C.is_similar(D) 

True 

sage: C.is_similar(D, transformation=True) 

Traceback (most recent call last): 

... 

RuntimeError: unable to compute transformation for similar matrices 

sage: C.jordan_form() 

Traceback (most recent call last): 

... 

RuntimeError: Some eigenvalue does not exist in 

Finite Field in a of size 7^2. 

  

An example over a finite field of prime order, which uses the 

algebraic closure of this field to find the change-of-basis 

matrix:: 

  

sage: cox = posets.TamariLattice(3).coxeter_transformation() 

sage: M = cox.change_ring(GF(3)) 

sage: M.is_similar(M**3, True) # long time 

( 

[1 0 0 0 0] 

[0 1 1 0 2] 

[0 0 0 0 1] 

[1 2 0 2 1] 

True, [0 0 1 0 0] 

) 

  

Inexact rings and fields are not supported. :: 

  

sage: A = matrix(CDF, 2, 2, range(4)) 

sage: B = copy(A) 

sage: A.is_similar(B) 

Traceback (most recent call last): 

... 

TypeError: matrix entries must come from an exact field, 

not Complex Double Field 

  

Base rings for the matrices need to have a fraction field. So 

in particular, the ring needs to be at least an integral domain. :: 

  

sage: Z6 = Integers(6) 

sage: A = matrix(Z6, 2, 2, range(4)) 

sage: A.is_similar(A) 

Traceback (most recent call last): 

... 

ValueError: base ring of a matrix needs a fraction field, 

maybe the ring is not an integral domain 

  

If the fraction fields of the entries are unequal and do not 

coerce in a common field, it is an error. :: 

  

sage: A = matrix(GF(3), 2, 2, range(4)) 

sage: B = matrix(GF(2), 2, 2, range(4)) 

sage: A.is_similar(B, transformation=True) 

Traceback (most recent call last): 

... 

TypeError: no common canonical parent for objects with parents: 

'Full MatrixSpace of 2 by 2 dense matrices over Finite Field 

of size 3' and 

'Full MatrixSpace of 2 by 2 dense matrices over Finite Field 

of size 2' 

  

A matrix over the integers and a matrix over the algebraic 

numbers will be compared over the algebraic numbers (by coercion 

of ``QQ`` in ``QQbar``). :: 

  

sage: A = matrix(ZZ, 2, 2, range(4)) 

sage: B = matrix(QQbar, 2, 2, range(4)) 

sage: A.is_similar(B) 

True 

  

TESTS: 

  

Inputs are checked. :: 

  

sage: A = matrix(ZZ, 2, 2, range(4)) 

sage: A.is_similar('garbage') 

Traceback (most recent call last): 

... 

TypeError: similarity requires a matrix as an argument, not garbage 

sage: B = copy(A) 

sage: A.is_similar(B, transformation='junk') 

Traceback (most recent call last): 

... 

ValueError: transformation keyword must be True or False 

  

Mismatched sizes raise an error:: 

  

sage: A = matrix(2, 2, range(4)) 

sage: B = matrix(3, 3, range(9)) 

sage: A.is_similar(B, transformation=True) 

Traceback (most recent call last): 

... 

ValueError: matrices do not have the same size 

  

Rectangular matrices and mismatched sizes raise an error:: 

  

sage: A = matrix(3, 2, range(6)) 

sage: B = copy(A) 

sage: A.is_similar(B) 

Traceback (most recent call last): 

... 

ValueError: similarity only makes sense for square matrices 

  

AUTHOR: 

  

- Rob Beezer (2011-03-15, 2015-05-25) 

""" 

from sage.structure.element import is_Matrix 

  

if not is_Matrix(other): 

raise TypeError('similarity requires a matrix as an argument, not {0}'.format(other)) 

if transformation not in [True, False]: 

raise ValueError('transformation keyword must be True or False') 

if not self.is_square() or not other.is_square(): 

raise ValueError('similarity only makes sense for square matrices') 

if self.nrows() != other.nrows(): 

raise ValueError('matrices do not have the same size') 

  

# convert to fraction fields for base rings 

try: 

A = self.matrix_over_field() 

B = other.matrix_over_field() 

except TypeError: 

mesg = "base ring of a matrix needs a fraction field, " 

mesg += "maybe the ring is not an integral domain" 

raise ValueError(mesg) 

if not have_same_parent(A, B): 

A, B = coercion_model.canonical_coercion(A, B) 

# base rings are equal now, via above check 

  

similar = (A.rational_form() == B.rational_form()) 

if not transformation: 

return similar 

elif not similar: 

return (False, None) 

else: 

# rational form routine does not provide transformation 

# so if possible, get transformations to Jordan form 

  

# first try to look for Jordan forms over the fraction field 

try: 

_, SA = A.jordan_form(transformation=True) 

_, SB = B.jordan_form(transformation=True) 

return (True, SB * SA.inverse()) 

except (ValueError, RuntimeError): 

pass 

  

# now move to the algebraic closure 

# so as to contain potential complex eigenvalues 

try: 

ring = A.base_ring() 

closure = ring.algebraic_closure() 

A = A.change_ring(closure) 

B = B.change_ring(closure) 

_, SA = A.jordan_form(transformation=True) 

_, SB = B.jordan_form(transformation=True) 

return (True, SB * SA.inverse()) 

except (ValueError, RuntimeError, NotImplementedError): 

raise RuntimeError('unable to compute transformation for similar matrices') 

  

def symplectic_form(self): 

r""" 

Find a symplectic form for self if self is an anti-symmetric, 

alternating matrix defined over a field. 

  

Returns a pair (F, C) such that the rows of C form a symplectic 

basis for self and F = C \* self \* C.transpose(). 

  

Raises a ValueError if not over a field, or self is not 

anti-symmetric, or self is not alternating. 

  

Anti-symmetric means that `M = -M^t`. Alternating means 

that the diagonal of `M` is identically zero. 

  

A symplectic basis is a basis of the form 

`e_1, \ldots, e_j, f_1, \ldots f_j, z_1, \dots, z_k` 

such that 

  

- `z_i M v^t` = 0 for all vectors `v` 

  

- `e_i M {e_j}^t = 0` for all `i, j` 

  

- `f_i M {f_j}^t = 0` for all `i, j` 

  

- `e_i M {f_i}^t = 1` for all `i` 

  

- `e_i M {f_j}^t = 0` for all `i` not equal 

`j`. 

  

See the example for a pictorial description of such a basis. 

  

EXAMPLES:: 

  

sage: E = matrix(QQ, 8, 8, [0, -1/2, -2, 1/2, 2, 0, -2, 1, 1/2, 0, -1, -3, 0, 2, 5/2, -3, 2, 1, 0, 3/2, -1, 0, -1, -2, -1/2, 3, -3/2, 0, 1, 3/2, -1/2, -1/2, -2, 0, 1, -1, 0, 0, 1, -1, 0, -2, 0, -3/2, 0, 0, 1/2, -2, 2, -5/2, 1, 1/2, -1, -1/2, 0, -1, -1, 3, 2, 1/2, 1, 2, 1, 0]); E 

[ 0 -1/2 -2 1/2 2 0 -2 1] 

[ 1/2 0 -1 -3 0 2 5/2 -3] 

[ 2 1 0 3/2 -1 0 -1 -2] 

[-1/2 3 -3/2 0 1 3/2 -1/2 -1/2] 

[ -2 0 1 -1 0 0 1 -1] 

[ 0 -2 0 -3/2 0 0 1/2 -2] 

[ 2 -5/2 1 1/2 -1 -1/2 0 -1] 

[ -1 3 2 1/2 1 2 1 0] 

sage: F, C = E.symplectic_form(); F 

[ 0 0 0 0 1 0 0 0] 

[ 0 0 0 0 0 1 0 0] 

[ 0 0 0 0 0 0 1 0] 

[ 0 0 0 0 0 0 0 1] 

[-1 0 0 0 0 0 0 0] 

[ 0 -1 0 0 0 0 0 0] 

[ 0 0 -1 0 0 0 0 0] 

[ 0 0 0 -1 0 0 0 0] 

sage: F == C * E * C.transpose() 

True 

""" 

import sage.matrix.symplectic_basis 

return sage.matrix.symplectic_basis.symplectic_basis_over_field(self) 

  

def _cyclic_subspace(self, v): 

r""" 

Helper function for computing with cyclic (Krylov) subspaces. 

  

For a square matrix `A` and a vector `v`, the cyclic subspace 

is spanned by the vectors 

  

.. MATH:: 

  

\{v, Av, A^2v, A^3v, \dots \} 

  

INPUT: 

  

- ``self`` - a square matrix over a field. 

  

- ``v`` - a vector with a degree equal to the size of the matrix. 

  

There is no explicit error-checking, it is the responsibility of 

the calling routine to provide accurate input. 

  

OUTPUT: 

  

Four related items are output. Principally this routine 

determines the dimension of a cyclic subspace, but also 

creates two bases for the subspace. Let `k` be the smallest 

integer such that `A^kv` is a linear combination of the 

products with smaller powers of `A`, i.e. the dimension 

of the cyclic subspace. 

  

- A list of the vectors `v, Av, A^2v,\dots, A^{k-1}v` 

(the "iterates"). These vectors give one basis of 

the subspace. 

  

- A list of scalars giving a linear combination of 

`v, Av, A^2v,\dots, A^kv` that equals the zero vector. 

This is the unique such set of such scalars where the 

last one in the list is 1. These can be used to form 

a monic polynomial in `A` that has `v` in its right kernel. 

the length of this list is `k+1`. 

  

- Form a matrix whose rows are the linearly independent iterates. 

Augment with a `k\times k` identity matrix. Apply row operations, 

scaling and adding multiples of rows, but never swap rows. Do 

this to create `k` pivot columns. The third output is this 

augmented, nearly row-reduced, matrix. The rows of the left 

portion will form a basis for the subspace, while the right 

portion will record linear combinations of the iterates that 

equal these basis vectors. 

  

- A list of length `k` with the location of the pivots 

in the augmented matrix. Specifically, entry ``i`` of this 

list is the column index of the pivot column containing its 

lone 1 in row ``i``. 

  

ALGORITHM: 

  

This could be called an "online echelon form" routine. As each 

new power of the matrix is built, the iterate is added to the bottom 

of the augmented matrix and row operations are used to update 

the pivot columns. Rows are never swapped, so this is not 

strictly reduced row-echelon form, but the running time will 

be similar. The main difference is that it "discovers" the 

dimension of the subspace as quickly as possible. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, [[5,4,2,1],[0,1,-1,-1],[-1,-1,3,0],[1,1,-1,2]]) 

sage: v = vector(QQ, [0,1,0,0]) 

sage: (QQ^4).span([v, A*v, A^2*v, A^3*v]).dimension() 

3 

  

sage: iterates, poly, augmented, pivots = A._cyclic_subspace(v) 

  

sage: iterates 

[(0, 1, 0, 0), (4, 1, -1, 1), (23, 1, -8, 8)] 

sage: poly 

[-16, 24, -9, 1] 

sage: lindep = iterates + [A^3*v] 

sage: sum(poly[i]*lindep[i] for i in range(4)) 

(0, 0, 0, 0) 

sage: B = sum(poly[i]*A^i for i in range(4)) 

sage: v in B.right_kernel() 

True 

  

sage: augmented 

[ 0 1 0 0 1 0 0] 

[ 1 0 0 0 -7/9 8/9 -1/9] 

[ 0 0 1 -1 -19/9 23/9 -4/9] 

sage: pivots 

[1, 0, 2] 

sage: transform = augmented[:, 4:7] 

sage: transform*matrix(iterates) == augmented[:, 0:4] 

True 

sage: (QQ^4).span(iterates) == (QQ^4).span(augmented[:, 0:4].rows()) 

True 

  

AUTHOR: 

  

- Rob Beezer (2011-05-20) 

""" 

cdef Py_ssize_t n, i, j, k, pivcol 

cdef Matrix aug 

n = self.ncols() 

aug = self.new_matrix(nrows=n+1, ncols=n+(n+1)) 

iterate = v.__copy__() 

iterates = [] 

pivots = [] 

for k in range(n+1): 

for j in range(n): 

aug[k, j] = iterate[j] 

# record keeping in augmented identity matrix 

aug[k, n+k] = 1 

# clear out pivot cols of row k, using pivots of previous rows 

for i in range(k): 

aug.add_multiple_of_row(k, i, -aug[k, pivots[i]]) 

# identify new pivot 

# no new pivot is all zeros, ie linear dependence 

pivcol = -1 

for j in range(n): 

if aug[k, j] != 0: 

pivcol = j 

pivots.append(pivcol) 

break 

# scale pivot, and clear its column 

if pivcol != -1: 

aug.rescale_row(k, 1/aug[k, pivcol]) 

for i in range(k): 

aug.add_multiple_of_row(i, k, -aug[i, pivcol]) 

iterates.append(iterate) 

iterate = self*iterate 

else: 

break 

poly = [] 

for j in range(n, n+k+1): 

poly.append(aug[k, j]) 

return iterates, poly, aug.submatrix(0, 0, k, n+k), pivots 

  

def cyclic_subspace(self, v, var=None, basis='echelon'): 

r""" 

Create a cyclic subspace for a vector, and optionally, 

a minimal polynomial for the iterated powers. 

  

These subspaces are also known as Krylov subspaces. They are 

spanned by the vectors 

  

.. MATH:: 

  

\{v, Av, A^2v, A^3v, \dots \} 

  

INPUT: 

  

- ``self`` - a square matrix with entries from a field. 

  

- ``v`` - a vector with a degree equal to the size of the matrix 

and entries compatible with the entries of the matrix. 

  

- ``var`` - default: ``None`` - if specified as a string or 

a generator of a polynomial ring, then this will be used 

to construct a polynomial reflecting a relation of linear 

dependence on the powers `A^iv` *and* this will cause 

the polynomial to be returned along with the subspace. 

A generator must create polynomials with coefficients from 

the same field as the matrix entries. 

  

- ``basis`` - default: ``echelon`` - the basis for the 

subspace is "echelonized" by default, but the keyword 

'iterates' will return a subspace with a user basis 

equal to the largest linearly independent 

set `\{v, Av, A^2v, A^3v, \dots, A^{k-1}v \}`. 

  

OUTPUT: 

  

Suppose `k` is the smallest power such that 

`\{v, Av, A^2v, A^3v, \dots, A^{k}v \}` is linearly 

dependent. Then the subspace returned will have 

dimension `k` and be spanned by the powers `0` through 

`k-1`. 

  

If a polynomial is requested through the use of the 

``var`` keyword, then a pair is returned, with the 

polynomial first and the subspace second. The polynomial 

is the unique monic polynomial whose coefficients provide 

a relation of linear dependence on the first `k` powers. 

  

For less convenient, but more flexible output, see the 

helper method "_cyclic_subspace" in this module. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, [[5,4,2,1],[0,1,-1,-1],[-1,-1,3,0],[1,1,-1,2]]) 

sage: v = vector(QQ, [0,1,0,0]) 

sage: E = A.cyclic_subspace(v); E 

Vector space of degree 4 and dimension 3 over Rational Field 

Basis matrix: 

[ 1 0 0 0] 

[ 0 1 0 0] 

[ 0 0 1 -1] 

sage: F = A.cyclic_subspace(v, basis='iterates'); F 

Vector space of degree 4 and dimension 3 over Rational Field 

User basis matrix: 

[ 0 1 0 0] 

[ 4 1 -1 1] 

[23 1 -8 8] 

sage: E == F 

True 

sage: p, S = A.cyclic_subspace(v, var='T'); p 

T^3 - 9*T^2 + 24*T - 16 

sage: p.degree() == E.dimension() 

True 

  

The polynomial has coefficients that yield a non-trivial 

relation of linear dependence on the iterates. Or, 

equivalently, evaluating the polynomial with the matrix 

will create a matrix that annihilates the vector. :: 

  

sage: A = matrix(QQ, [[15, 37/3, -16, -104/3, -29, -7/3, 35, 2/3, -29/3, -1/3], 

....: [ 2, 9, -1, -6, -6, 0, 7, 0, -2, 0], 

....: [24, 74/3, -29, -208/3, -58, -14/3, 70, 4/3, -58/3, -2/3], 

....: [-6, -19, 3, 21, 19, 0, -21, 0, 6, 0], 

....: [2, 6, -1, -6, -3, 0, 7, 0, -2, 0], 

....: [-96, -296/3, 128, 832/3, 232, 65/3, -279, -16/3, 232/3, 8/3], 

....: [0, 0, 0, 0, 0, 0, 3, 0, 0, 0], 

....: [20, 26/3, -30, -199/3, -42, -14/3, 70, 13/3, -55/3, -2/3], 

....: [18, 57, -9, -54, -57, 0, 63, 0, -15, 0], 

....: [0, 0, 0, 0, 0, 0, 0, 0, 0, 3]]) 

sage: u = zero_vector(QQ, 10); u[0] = 1 

sage: p, S = A.cyclic_subspace(u, var='t', basis='iterates') 

sage: S 

Vector space of degree 10 and dimension 3 over Rational Field 

User basis matrix: 

[ 1 0 0 0 0 0 0 0 0 0] 

[ 15 2 24 -6 2 -96 0 20 18 0] 

[ 79 12 140 -36 12 -560 0 116 108 0] 

sage: p 

t^3 - 9*t^2 + 27*t - 27 

sage: k = p.degree() 

sage: coeffs = p.list() 

sage: iterates = S.basis() + [A^k*u] 

sage: sum(coeffs[i]*iterates[i] for i in range(k+1)) 

(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 

sage: u in p(A).right_kernel() 

True 

  

TESTS: 

  

A small case. :: 

  

sage: A = matrix(QQ, 5, range(25)) 

sage: u = zero_vector(QQ, 5) 

sage: A.cyclic_subspace(u) 

Vector space of degree 5 and dimension 0 over Rational Field 

Basis matrix: 

[] 

  

Various problem inputs. Notice the vector must have entries 

that coerce into the base ring of the matrix, and a polynomial 

ring generator must have a base ring that agrees with the 

base ring of the matrix. :: 

  

sage: A = matrix(QQ, 4, range(16)) 

sage: v = vector(QQ, 4, range(4)) 

  

sage: A.cyclic_subspace('junk') 

Traceback (most recent call last): 

... 

TypeError: first input should be a vector, not junk 

  

sage: A.cyclic_subspace(v, var=sin(x)) 

Traceback (most recent call last): 

... 

TypeError: polynomial variable must be a string or polynomial ring generator, not sin(x) 

  

sage: t = polygen(GF(7), 't') 

sage: A.cyclic_subspace(v, var=t) 

Traceback (most recent call last): 

... 

TypeError: polynomial generator must be over the same ring as the matrix entries 

  

sage: A.cyclic_subspace(v, basis='garbage') 

Traceback (most recent call last): 

... 

ValueError: basis format must be 'echelon' or 'iterates', not garbage 

  

sage: B = matrix(QQ, 4, 5, range(20)) 

sage: B.cyclic_subspace(v) 

Traceback (most recent call last): 

... 

TypeError: matrix must be square, not 4 x 5 

  

sage: C = matrix(QQ, 5, 5, range(25)) 

sage: C.cyclic_subspace(v) 

Traceback (most recent call last): 

... 

TypeError: vector must have degree equal to the size of the matrix, not 4 

  

sage: D = matrix(RDF, 4, 4, range(16)) 

sage: D.cyclic_subspace(v) 

Traceback (most recent call last): 

... 

TypeError: matrix entries must be from an exact ring, not Real Double Field 

  

sage: E = matrix(Integers(6), 4, 4, range(16)) 

sage: E.cyclic_subspace(v) 

Traceback (most recent call last): 

... 

TypeError: matrix entries must be from an exact field, not Ring of integers modulo 6 

  

sage: F.<a> = GF(2^4) 

sage: G = matrix(QQ, 4, range(16)) 

sage: w = vector(F, 4, [1, a, a^2, a^3]) 

sage: G.cyclic_subspace(w) 

Traceback (most recent call last): 

... 

TypeError: unable to make vector entries compatible with matrix entries 

  

AUTHOR: 

  

- Rob Beezer (2011-05-20) 

""" 

import sage.rings.polynomial.polynomial_ring 

n = self.ncols() 

R = self.base_ring() 

if not is_Vector(v): 

raise TypeError('first input should be a vector, not {0}'.format(v)) 

if not (var is None or isinstance(var, basestring)): 

generator = False 

try: 

generator = var.is_gen() 

except AttributeError: 

pass 

if not generator: 

raise TypeError('polynomial variable must be a string or polynomial ring generator, not {0}'.format(var)) 

elif var.base_ring() != R: 

raise TypeError('polynomial generator must be over the same ring as the matrix entries') 

if not basis in ['echelon', 'iterates']: 

raise ValueError("basis format must be 'echelon' or 'iterates', not {0}".format(basis)) 

if not self.is_square(): 

raise TypeError('matrix must be square, not {0} x {1}'.format(self.nrows(), self.ncols())) 

if v.degree() != n: 

raise TypeError('vector must have degree equal to the size of the matrix, not {0}'.format(v.degree())) 

if not (R.is_field() and R.is_exact()): 

try: 

fraction_field = R.fraction_field() 

except TypeError: 

raise TypeError('matrix entries must be from an exact field, not {0}'.format(R)) 

if fraction_field.is_exact(): 

return self.change_ring(R.fraction_field()).cyclic_subspace(v, var, basis) 

raise TypeError('matrix entries must be from an exact ring, not {0}'.format(R)) 

try: 

v = v.change_ring(R) 

except TypeError: 

raise TypeError('unable to make vector entries compatible with matrix entries') 

  

iterates, poly, augmented, pivots = self._cyclic_subspace(v) 

k = len(pivots) 

polynomial = not var is None 

if polynomial: 

x = sage.rings.polynomial.polynomial_ring.polygen(R, var) 

poly = sum([poly[i] * x**i for i in range(len(poly))]) 

ambient = R**n 

if basis == 'echelon': 

echelon = [] 

pivot_col_row = [(v, i) for i, v in enumerate(pivots)] 

pivot_col_row.sort() 

aug = augmented.submatrix(0, 0, k, n) 

for _, pivrow in pivot_col_row: 

echelon.append(aug.row(pivrow)) 

subspace = ambient.subspace(echelon, check=False, already_echelonized=True) 

elif basis == 'iterates': 

subspace = ambient.subspace_with_basis(iterates, check=False) 

if polynomial: 

return poly, subspace 

else: 

return subspace 

  

def _cholesky_decomposition_(self): 

r""" 

Return the Cholesky decomposition of ``self``; see ``cholesky_decomposition``. 

  

This generic implementation uses a standard recursion. 

""" 

L = self.fetch('cholesky_broken') 

if L is None: 

A = self.__copy__() 

L = A.parent()(0) 

n = self.nrows() 

for k in range(0, n-1 + 1): 

try: 

L[k, k] = A[k, k].sqrt() 

except TypeError: 

raise ValueError("The input matrix was not symmetric and positive definite") 

  

for s in range(k+1, n): 

L[s, k] = A[s, k] / L[k, k] 

for j in range(k+1, n): 

for i in range(j, n): 

A[i, j] -= L[i, k]*L[j, k].conjugate() 

L.set_immutable() 

self.cache('cholesky_broken', L) 

return L 

  

def cholesky(self): 

r""" 

Returns the Cholesky decomposition of a symmetric or Hermitian matrix. 

  

INPUT: 

  

A square matrix that is real, symmetric and positive definite. 

Or a square matrix that is complex, Hermitian and positive 

definite. Generally, the base ring for the entries of the 

matrix needs to be a subfield of the algebraic numbers 

(``QQbar``). Examples include the rational numbers (``QQ``), 

some number fields, and real algebraic numbers and the 

algebraic numbers themselves. 

  

OUTPUT: 

  

For a matrix `A` the routine returns a lower triangular 

matrix `L` such that, 

  

.. MATH:: 

  

A = LL^\ast 

  

where `L^\ast` is the conjugate-transpose in the complex case, 

and just the transpose in the real case. If the matrix 

fails to be positive definite (perhaps because it is not 

symmetric or Hermitian), then a ``ValueError`` results. 

  

ALGORITHM: 

  

Whether or not the matrix is positive definite is checked 

first in every case. This is accomplished with an 

indefinite factorization (see :meth:`indefinite_factorization`) 

which caches its result. This algorithm is of an order `n^3/3`. 

If the matrix is positive definite, this computation always 

succeeds, using just field operations. The transition to a 

Cholesky decomposition "only" requires computing square roots 

of the positive (real) entries of the diagonal matrix produced in 

the indefinite factorization. Hence, there is no real penalty 

in the positive definite check (here, or prior to calling this 

routine), but a field extension with square roots may not be 

implemented in all reasonable cases. 

  

EXAMPLES: 

  

This simple example has a result with entries that remain 

in the field of rational numbers. :: 

  

sage: A = matrix(QQ, [[ 4, -2, 4, 2], 

....: [-2, 10, -2, -7], 

....: [ 4, -2, 8, 4], 

....: [ 2, -7, 4, 7]]) 

sage: A.is_symmetric() 

True 

sage: L = A.cholesky() 

sage: L 

[ 2 0 0 0] 

[-1 3 0 0] 

[ 2 0 2 0] 

[ 1 -2 1 1] 

sage: L.parent() 

Full MatrixSpace of 4 by 4 dense matrices over Rational Field 

sage: L*L.transpose() == A 

True 

  

This seemingly simple example requires first moving to 

the rational numbers for field operations, and then square 

roots necessitate that the result has entries in the field 

of algebraic numbers. :: 

  

sage: A = matrix(ZZ, [[ 78, -30, -37, -2], 

....: [-30, 102, 179, -18], 

....: [-37, 179, 326, -38], 

....: [ -2, -18, -38, 15]]) 

sage: A.is_symmetric() 

True 

sage: L = A.cholesky() 

sage: L 

[ 8.83176086632785? 0 0 0] 

[ -3.396831102433787? 9.51112708681461? 0 0] 

[ -4.189425026335004? 17.32383862241232? 2.886751345948129? 0] 

[-0.2264554068289192? -1.973397116652010? -1.649572197684645? 2.886751345948129?] 

sage: L.parent() 

Full MatrixSpace of 4 by 4 dense matrices over Algebraic Real Field 

sage: L*L.transpose() == A 

True 

  

Some subfields of the complex numbers, such as this number 

field of complex numbers with rational real and imaginary parts, 

allow for this computation. :: 

  

sage: C.<I> = QuadraticField(-1) 

sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I], 

....: [ -17*I + 3, 38, -69*I + 89, 7*I + 15], 

....: [-24*I + 25, 69*I + 89, 976, 24*I + 6], 

....: [ -21*I, -7*I + 15, -24*I + 6, 28]]) 

sage: A.is_hermitian() 

True 

sage: L = A.cholesky() 

sage: L 

[ 4.79...? 0 0 0] 

[ 0.62...? - 3.54...?*I 5.00...? 0 0] 

[ 5.21...? - 5.00...?*I 13.58...? + 10.72...?*I 24.98...? 0] 

[ -4.37...?*I -0.10...? - 0.85...?*I -0.21...? + 0.37...?*I 2.81...?] 

sage: L.parent() 

Full MatrixSpace of 4 by 4 dense matrices over Algebraic Field 

sage: (L*L.conjugate_transpose() - A.change_ring(QQbar)).norm() < 10^-10 

True 

  

The field of algebraic numbers is an ideal setting for this 

computation. :: 

  

sage: A = matrix(QQbar, [[ 2, 4 + 2*I, 6 - 4*I], 

....: [ -2*I + 4, 11, 10 - 12*I], 

....: [ 4*I + 6, 10 + 12*I, 37]]) 

sage: A.is_hermitian() 

True 

sage: L = A.cholesky() 

sage: L 

[ 1.414213562373095? 0 0] 

[2.828427124746190? - 1.414213562373095?*I 1 0] 

[4.242640687119285? + 2.828427124746190?*I -2*I + 2 1.732050807568878?] 

sage: L.parent() 

Full MatrixSpace of 3 by 3 dense matrices over Algebraic Field 

sage: (L*L.conjugate_transpose() - A.change_ring(QQbar)).norm() < 10^-10 

True 

  

  

Results are cached, hence immutable. Use the ``copy`` function 

if you need to make a change. :: 

  

sage: A = matrix(QQ, [[ 4, -2, 4, 2], 

....: [-2, 10, -2, -7], 

....: [ 4, -2, 8, 4], 

....: [ 2, -7, 4, 7]]) 

sage: L = A.cholesky() 

sage: L.is_immutable() 

True 

  

sage: from copy import copy 

sage: LC = copy(L) 

sage: LC[0,0] = 1000 

sage: LC 

[1000 0 0 0] 

[ -1 3 0 0] 

[ 2 0 2 0] 

[ 1 -2 1 1] 

  

There are a variety of situations which will prevent the computation of a Cholesky decomposition. 

  

The base ring must be exact. For numerical work, create a 

matrix with a base ring of ``RDF`` or ``CDF`` and use the 

:meth:`~sage.matrix.matrix_double_dense.Matrix_double_dense.cholesky` 

method for matrices of that type. :: 

  

sage: F = RealField(100) 

sage: A = matrix(F, [[1.0, 3.0], [3.0, -6.0]]) 

sage: A.cholesky() 

Traceback (most recent call last): 

... 

TypeError: base ring of the matrix must be exact, not Real Field with 100 bits of precision 

  

The base ring may not have a fraction field. :: 

  

sage: A = matrix(Integers(6), [[2, 0], [0, 4]]) 

sage: A.cholesky() 

Traceback (most recent call last): 

... 

ValueError: Could not see Ring of integers modulo 6 as a subring of 

the real or complex numbers 

  

The base field may not have elements that are comparable to zero. :: 

  

sage: F.<a> = FiniteField(5^4) 

sage: A = matrix(F, [[2+a^3, 3], [3, 3]]) 

sage: A.cholesky() 

Traceback (most recent call last): 

... 

ValueError: Could not see Finite Field in a of size 5^4 as a subring 

of the real or complex numbers 

  

The algebraic closure of the fraction field of the base ring may not be implemented. :: 

  

sage: F = Integers(7) 

sage: A = matrix(F, [[4, 0], [0, 3]]) 

sage: A.cholesky() 

Traceback (most recent call last): 

... 

ValueError: Could not see Ring of integers modulo 7 as a subring of 

the real or complex numbers 

  

The matrix may not be positive definite. :: 

  

sage: C.<I> = QuadraticField(-1) 

sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I], 

....: [4 + 2*I, 8, 10*I], 

....: [2 - 2*I, -10*I, -3]]) 

sage: B.is_positive_definite() 

False 

sage: B.cholesky() 

Traceback (most recent call last): 

... 

ValueError: matrix is not positive definite, 

so cannot compute Cholesky decomposition 

  

The matrix could be positive semi-definite, and thus 

lack a Cholesky decomposition. :: 

  

sage: A = matrix(QQ, [[21, 15, 12, -3], 

....: [15, 12, 9, 12], 

....: [12, 9, 7, 3], 

....: [-3, 12, 3, 8]]) 

sage: A.is_positive_definite() 

False 

sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)] 

[21, 27, 0, 0] 

sage: A.cholesky() 

Traceback (most recent call last): 

... 

ValueError: matrix is not positive definite, 

so cannot compute Cholesky decomposition 

  

TESTS: 

  

This verifies that :trac:`11274` is resolved. :: 

  

sage: E = matrix(QQ, [[2, 1], [1, 1]]) 

sage: E.is_symmetric() 

True 

sage: E.eigenvalues() 

[0.38...?, 2.61...?] 

sage: E.det() 

1 

sage: E.cholesky() 

[ 1.414213562373095? 0] 

[0.7071067811865475? 0.7071067811865475?] 

  

We check that if the input is a real matrix then the output is real as 

well (:trac:`18381`):: 

  

sage: E = matrix(QQ, [[4, 2], [2, 10/9]]) 

sage: E.cholesky().base_ring() 

Rational Field 

  

sage: E = matrix(QQ, [[2, 1], [1, 1]]) 

sage: E.cholesky().base_ring() 

Algebraic Real Field 

  

AUTHOR: 

  

- Rob Beezer (2012-05-27) 

""" 

from copy import copy 

C = self.fetch('cholesky') 

if C is None: 

if not self.is_square(): 

msg = "matrix must be square, not {0} x {1}" 

raise ValueError(msg.format(self.nrows(), self.ncols())) 

if not self.base_ring().is_exact(): 

msg = 'base ring of the matrix must be exact, not {0}' 

raise TypeError(msg.format(self.base_ring())) 

if not self.is_positive_definite(): 

msg = 'matrix is not positive definite, so cannot compute Cholesky decomposition' 

raise ValueError(msg) 

# the successful positive definite check will cache a Hermitian 

# or symmetric indefinite factorization, as appropriate 

factors = self.fetch('indefinite_factorization_hermitian') 

if factors is None: 

factors = self.fetch('indefinite_factorization_symmetric') 

from sage.rings.qqbar import AA as F_ac 

else: 

from sage.rings.qqbar import QQbar as F_ac 

  

L = factors[0] 

d = factors[1] 

F = L.base_ring() # field really 

splits = [] # square roots of diagonal entries 

extend = False 

for x in d: 

if not extend and x.is_square(): 

sqrt = x.sqrt() 

else: 

extend = True 

sqrt = F_ac(x).sqrt() 

splits.append(sqrt) 

# move square root of the diagonal matrix 

# into the lower triangular matrix 

# We need a copy, to break immutability 

# and the field may have changed as well 

if extend: 

C = L.change_ring(F_ac) 

else: 

C = L.__copy__() 

  

for c in range(C.ncols()): 

C.rescale_col(c, splits[c]) 

C.set_immutable() 

self.cache('cholesky', C) 

return C 

  

def LU(self, pivot=None, format='plu'): 

r""" 

Finds a decomposition into a lower-triangular matrix and 

an upper-triangular matrix. 

  

INPUT: 

  

- ``pivot`` - pivoting strategy 

  

- 'auto' (default) - see if the matrix entries are 

ordered (i.e. if they have an absolute value method), 

and if so, use a the partial pivoting strategy. 

Otherwise, fall back to the nonzero strategy. This 

is the best choice for general routines that may 

call this for matrix entries of a variety of types. 

  

- 'partial' - each column is examined for 

the element with the largest absolute value and the 

row containing this element is swapped into place. 

  

- 'nonzero' - the first nonzero element in a column 

is located and the row with this element is used. 

  

- ``format`` - contents of output, see more discussion 

below about output. 

  

- 'plu' (default) - a triple; matrices P, L and U 

such that A = P*L*U. 

  

- 'compact' - a pair; row permutation as a tuple, and the 

matrices L and U combined into one matrix. 

  

OUTPUT: 

  

Suppose that `A` is an `m\times n` matrix, then an LU 

decomposition is a lower-triangular `m\times m` matrix 

`L` with every diagonal element equal to 1, and an 

upper-triangular `m\times n` matrix, `U` such that the 

product `LU`, after a permutation of the rows, is then 

equal to `A`. For the 'plu' format the permutation is 

returned as an `m\times m` permutation matrix `P` such 

that 

  

.. MATH:: 

  

A = PLU 

  

It is more common to place the permutation matrix just 

to the left of `A`. If you desire this version, then 

use the inverse of `P` which is computed most efficiently 

as its transpose. 

  

If the 'partial' pivoting strategy is used, then the 

non-diagonal entries of `L` will be less than or equal 

to 1 in absolute value. The 'nonzero' pivot strategy may 

be faster, but the growth of data structures for elements of 

the decomposition might counteract the advantage. 

  

By necessity, returned matrices have a base ring equal 

to the fraction field of the base ring of the original matrix. 

  

In the 'compact' format, the first returned value is a 

tuple that is a permutation of the rows of `LU` that yields 

`A`. See the doctest for how you might employ this 

permutation. Then the matrices `L` and `U` are merged 

into one matrix -- remove the diagonal of ones in `L` 

and the remaining nonzero entries can replace the 

entries of `U` beneath the diagonal. 

  

The results are cached, only in the compact format, separately 

for each pivot strategy called. Repeated requests for the 

'plu' format will require just a small amount of overhead 

in each call to bust out the compact format to the three 

matrices. Since only the compact format is cached, the 

components of the compact format are immutable, while the 

components of the 'plu' format are regenerated, and hence 

are mutable. 

  

Notice that while `U` is similar to row-echelon form and the 

rows of `U` span the row space of `A`, the rows of `U` are not 

generally linearly independent. Nor are the pivot columns 

(or rank) immediately obvious. However for rings without 

specialized echelon form routines, this method is about 

twice as fast as the generic echelon form routine since 

it only acts "below the diagonal", as would be predicted 

from a theoretical analysis of the algorithms. 

  

.. NOTE:: 

  

This is an exact computation, so limited to exact 

rings. If you need numerical results, convert the 

base ring to the field of real double numbers, 

``RDF`` or the field of complex double numbers, 

``CDF``, which will use a faster routine that 

is careful about numerical subtleties. 

  

ALGORITHM: 

  

"Gaussian Elimination with Partial Pivoting," 

Algorithm 21.1 of [TB1997]_. 

  

EXAMPLES: 

  

Notice the difference in the `L` matrix as a result of different 

pivoting strategies. With partial pivoting, every entry of `L` 

has absolute value 1 or less. :: 

  

sage: A = matrix(QQ, [[1, -1, 0, 2, 4, 7, -1], 

....: [2, -1, 0, 6, 4, 8, -2], 

....: [2, 0, 1, 4, 2, 6, 0], 

....: [1, 0, -1, 8, -1, -1, -3], 

....: [1, 1, 2, -2, -1, 1, 3]]) 

sage: P, L, U = A.LU(pivot='partial') 

sage: P 

[0 0 0 0 1] 

[1 0 0 0 0] 

[0 0 0 1 0] 

[0 0 1 0 0] 

[0 1 0 0 0] 

sage: L 

[ 1 0 0 0 0] 

[ 1/2 1 0 0 0] 

[ 1/2 1/3 1 0 0] 

[ 1 2/3 1/5 1 0] 

[ 1/2 -1/3 -2/5 0 1] 

sage: U 

[ 2 -1 0 6 4 8 -2] 

[ 0 3/2 2 -5 -3 -3 4] 

[ 0 0 -5/3 20/3 -2 -4 -10/3] 

[ 0 0 0 0 2/5 4/5 0] 

[ 0 0 0 0 1/5 2/5 0] 

sage: A == P*L*U 

True 

sage: P, L, U = A.LU(pivot='nonzero') 

sage: P 

[1 0 0 0 0] 

[0 1 0 0 0] 

[0 0 1 0 0] 

[0 0 0 1 0] 

[0 0 0 0 1] 

sage: L 

[ 1 0 0 0 0] 

[ 2 1 0 0 0] 

[ 2 2 1 0 0] 

[ 1 1 -1 1 0] 

[ 1 2 2 0 1] 

sage: U 

[ 1 -1 0 2 4 7 -1] 

[ 0 1 0 2 -4 -6 0] 

[ 0 0 1 -4 2 4 2] 

[ 0 0 0 0 1 2 0] 

[ 0 0 0 0 -1 -2 0] 

sage: A == P*L*U 

True 

  

An example of the compact format. :: 

  

sage: B = matrix(QQ, [[ 1, 3, 5, 5], 

....: [ 1, 4, 7, 8], 

....: [-1, -4, -6, -6], 

....: [ 0, -2, -5, -8], 

....: [-2, -6, -6, -2]]) 

sage: perm, M = B.LU(format='compact') 

sage: perm 

(4, 3, 0, 1, 2) 

sage: M 

[ -2 -6 -6 -2] 

[ 0 -2 -5 -8] 

[-1/2 0 2 4] 

[-1/2 -1/2 3/4 0] 

[ 1/2 1/2 -1/4 0] 

  

We can easily illustrate the relationships between 

the two formats with a square matrix. :: 

  

sage: C = matrix(QQ, [[-2, 3, -2, -5], 

....: [ 1, -2, 1, 3], 

....: [-4, 7, -3, -8], 

....: [-3, 8, -1, -5]]) 

sage: P, L, U = C.LU(format='plu') 

sage: perm, M = C.LU(format='compact') 

sage: (L - identity_matrix(4)) + U == M 

True 

sage: p = [perm[i]+1 for i in range(len(perm))] 

sage: PP = Permutation(p).to_matrix() 

sage: PP == P 

True 

  

For a nonsingular matrix, and the 'nonzero' pivot 

strategy there is no need to permute rows, so the 

permutation matrix will be the identity. Furthermore, 

it can be shown that then the `L` and `U` matrices 

are uniquely determined by requiring `L` to have ones 

on the diagonal. :: 

  

sage: D = matrix(QQ, [[ 1, 0, 2, 0, -2, -1], 

....: [ 3, -2, 3, -1, 0, 6], 

....: [-4, 2, -3, 1, -1, -8], 

....: [-2, 2, -3, 2, 1, 0], 

....: [ 0, -1, -1, 0, 2, 5], 

....: [-1, 2, -4, -1, 5, -3]]) 

sage: P, L, U = D.LU(pivot='nonzero') 

sage: P 

[1 0 0 0 0 0] 

[0 1 0 0 0 0] 

[0 0 1 0 0 0] 

[0 0 0 1 0 0] 

[0 0 0 0 1 0] 

[0 0 0 0 0 1] 

sage: L 

[ 1 0 0 0 0 0] 

[ 3 1 0 0 0 0] 

[ -4 -1 1 0 0 0] 

[ -2 -1 -1 1 0 0] 

[ 0 1/2 1/4 1/2 1 0] 

[ -1 -1 -5/2 -2 -6 1] 

sage: U 

[ 1 0 2 0 -2 -1] 

[ 0 -2 -3 -1 6 9] 

[ 0 0 2 0 -3 -3] 

[ 0 0 0 1 0 4] 

[ 0 0 0 0 -1/4 -3/4] 

[ 0 0 0 0 0 1] 

sage: D == L*U 

True 

  

The base ring of the matrix may be any field, or a ring 

which has a fraction field implemented in Sage. The ring 

needs to be exact (there is a numerical LU decomposition 

for matrices over ``RDF`` and ``CDF``). Matrices returned 

are over the original field, or the fraction field of the 

ring. If the field is not ordered (i.e. the absolute value 

function is not implemented), then the pivot strategy needs 

to be 'nonzero'. :: 

  

sage: A = matrix(RealField(100), 3, 3, range(9)) 

sage: P, L, U = A.LU() 

Traceback (most recent call last): 

... 

TypeError: base ring of the matrix must be exact, not Real Field with 100 bits of precision 

  

sage: A = matrix(Integers(6), 3, 2, range(6)) 

sage: A.LU() 

Traceback (most recent call last): 

... 

TypeError: base ring of the matrix needs a field of fractions, not Ring of integers modulo 6 

  

sage: R.<y> = PolynomialRing(QQ, 'y') 

sage: B = matrix(R, [[y+1, y^2+y], [y^2, y^3]]) 

sage: P, L, U = B.LU(pivot='partial') 

Traceback (most recent call last): 

... 

TypeError: cannot take absolute value of matrix entries, try 'pivot=nonzero' 

sage: P, L, U = B.LU(pivot='nonzero') 

sage: P 

[1 0] 

[0 1] 

sage: L 

[ 1 0] 

[y^2/(y + 1) 1] 

sage: U 

[ y + 1 y^2 + y] 

[ 0 0] 

sage: L.base_ring() 

Fraction Field of Univariate Polynomial Ring in y over Rational Field 

sage: B == P*L*U 

True 

  

sage: F.<a> = FiniteField(5^2) 

sage: C = matrix(F, [[a + 3, 4*a + 4, 2, 4*a + 2], 

....: [3, 2*a + 4, 2*a + 4, 2*a + 1], 

....: [3*a + 1, a + 3, 2*a + 4, 4*a + 3], 

....: [a, 3, 3*a + 1, a]]) 

sage: P, L, U = C.LU(pivot='nonzero') 

sage: P 

[1 0 0 0] 

[0 1 0 0] 

[0 0 1 0] 

[0 0 0 1] 

sage: L 

[ 1 0 0 0] 

[3*a + 3 1 0 0] 

[ 2*a 4*a + 2 1 0] 

[2*a + 3 2 2*a + 4 1] 

sage: U 

[ a + 3 4*a + 4 2 4*a + 2] 

[ 0 a + 1 a + 3 2*a + 4] 

[ 0 0 1 4*a + 2] 

[ 0 0 0 0] 

sage: L.base_ring() 

Finite Field in a of size 5^2 

sage: C == P*L*U 

True 

  

With no pivoting strategy given (i.e. ``pivot=None``) 

the routine will try to use partial pivoting, but then 

fall back to the nonzero strategy. For the nonsingular 

matrix below, we see evidence of pivoting when viewed 

over the rationals, and no pivoting over the integers 

mod 29. :: 

  

sage: entries = [3, 20, 11, 7, 16, 28, 5, 15, 21, 23, 22, 18, 8, 23, 15, 2] 

sage: A = matrix(Integers(29), 4, 4, entries) 

sage: perm, _ = A.LU(format='compact'); perm 

(0, 1, 2, 3) 

sage: B = matrix(QQ, 4, 4, entries) 

sage: perm, _ = B.LU(format='compact'); perm 

(2, 0, 1, 3) 

  

The `U` matrix is only guaranteed to be upper-triangular. 

The rows are not necessarily linearly independent, nor are 

the pivots columns or rank in evidence. :: 

  

sage: A = matrix(QQ, [[ 1, -4, 1, 0, -2, 1, 3, 3, 2], 

....: [-1, 4, 0, -4, 0, -4, 5, -7, -7], 

....: [ 0, 0, 1, -4, -1, -3, 6, -5, -6], 

....: [-2, 8, -1, -4, 2, -4, 1, -8, -7], 

....: [ 1, -4, 2, -4, -3, 2, 5, 6, 4]]) 

sage: P, L, U = A.LU() 

sage: U 

[ -2 8 -1 -4 2 -4 1 -8 -7] 

[ 0 0 1/2 -2 -1 -2 9/2 -3 -7/2] 

[ 0 0 3/2 -6 -2 0 11/2 2 1/2] 

[ 0 0 0 0 -1/3 -1 5/3 -5/3 -5/3] 

[ 0 0 0 0 1/3 -3 7/3 -19/3 -19/3] 

sage: A.rref() 

[ 1 -4 0 4 0 0 -1 -1 -1] 

[ 0 0 1 -4 0 0 1 0 -1] 

[ 0 0 0 0 1 0 -2 -1 -1] 

[ 0 0 0 0 0 1 -1 2 2] 

[ 0 0 0 0 0 0 0 0 0] 

sage: A.pivots() 

(0, 2, 4, 5) 

  

TESTS: 

  

Unknown keywords are caught. :: 

  

sage: A = matrix(ZZ, 2, range(4)) 

sage: A.LU(pivot='junk') 

Traceback (most recent call last): 

... 

ValueError: pivot strategy must be None, 'partial' or 'nonzero', not junk 

sage: A.LU(format='garbage') 

Traceback (most recent call last): 

... 

ValueError: format must be 'plu' or 'compact', not garbage 

  

Components of the 'compact' format are immutable, while 

components of the 'plu' format are not. :: 

  

sage: A = matrix(ZZ, 2, range(4)) 

sage: perm, M = A.LU(format='compact') 

sage: perm[0] = 25 

Traceback (most recent call last): 

... 

TypeError: 'tuple' object does not support item assignment 

sage: M.is_immutable() 

True 

sage: P, L, U = A.LU(format='plu') 

sage: all([A.is_mutable() for A in [P, L, U]]) 

True 

  

Partial pivoting is based on the absolute values of entries 

of a column. :trac:`12208` shows that the return value of the 

absolute value must be handled carefully. This tests that 

situation in the case of cylotomic fields. :: 

  

sage: C = SymmetricGroup(5).character_table() 

sage: C.base_ring() 

Cyclotomic Field of order 1 and degree 1 

sage: P, L, U = C.LU(pivot='partial') 

sage: C == P*L*U 

True 

  

AUTHOR: 

  

- Rob Beezer (2011-04-26) 

""" 

if not pivot in [None, 'partial', 'nonzero']: 

msg = "pivot strategy must be None, 'partial' or 'nonzero', not {0}" 

raise ValueError(msg.format(pivot)) 

if not format in ['compact', 'plu']: 

msg = "format must be 'plu' or 'compact', not {0}" 

raise ValueError(msg.format(format)) 

  

# exact rings only, must have fraction field 

R = self.base_ring() 

if not R.is_exact(): 

msg = 'base ring of the matrix must be exact, not {0}' 

raise TypeError(msg.format(R)) 

if not R.is_field(): 

try: 

F = R.fraction_field() 

except Exception: 

msg = 'base ring of the matrix needs a field of fractions, not {0}' 

raise TypeError(msg.format(R)) 

else: 

F = R 

  

# 'nonzero' strategy passes through untouched 

# 'partial' survives iff field has absolute value 

# None will use 'partial' iff possible, else fallback to nonzero 

if pivot in [None, 'partial']: 

try: 

abs(F.an_element()) 

pivot = 'partial' 

except Exception: 

if pivot == 'partial': 

msg = "cannot take absolute value of matrix entries, try 'pivot=nonzero'" 

raise TypeError(msg) 

pivot = 'nonzero' 

partial = (pivot == 'partial') 

  

cdef Py_ssize_t m, n, d, i, j, k, p, max_location 

cdef Matrix M 

  

# can now access cache, else compute 

# the compact version of LU decomposition 

key = 'LU_' + pivot 

compact = self.fetch(key) 

if compact is None: 

if F == R: 

M = self.__copy__() 

else: 

M = self.change_ring(F) 

m, n = M._nrows, M._ncols 

d = min(m, n) 

perm = list(xrange(m)) 

zero = F(0) 

for k in range(d): 

max_location = -1 

if partial: 

# abs() necessary to convert zero to the 

# correct type for comparisons (Trac #12208) 

max_entry = abs(zero) 

for i in range(k,m): 

entry = abs(M.get_unsafe(i,k)) 

if entry > max_entry: 

max_location = i 

max_entry = entry 

else: 

for i in range(k,m): 

if M.get_unsafe(i,k) != zero: 

max_location = i 

break 

if max_location != -1: 

perm[k], perm[max_location] = perm[max_location], perm[k] 

M.swap_rows(k, max_location) 

for j in range(k+1, m): 

scale = -M.get_unsafe(j,k)/M.get_unsafe(k,k) 

M.set_unsafe(j,k, -scale) 

for p in range(k+1,n): 

M.set_unsafe(j,p, M.get_unsafe(j,p) + scale*M.get_unsafe(k,p)) 

perm = tuple(perm) 

M.set_immutable() 

compact = (perm, M) 

self.cache(key, compact) 

  

if format == 'compact': 

return compact 

elif format == 'plu': 

import sage.combinat.permutation 

perm = compact[0] 

M = compact[1].__copy__() 

F = M.base_ring() 

m, n = M._nrows, M._ncols 

d = min(m, n) 

zero = F(0) 

perm = [perm[i]+1 for i in range(m)] 

P = sage.combinat.permutation.Permutation(perm).to_matrix() 

L = M.matrix_space(m,m).identity_matrix().__copy__() 

for i in range(1, m): 

for k in range(min(i,d)): 

L[i,k] = M[i,k] 

M[i,k] = zero 

return P, L, M 

  

def _indefinite_factorization(self, algorithm, check=True): 

r""" 

Utility function to decomposes a symmetric or 

Hermitian matrix into a lower triangular matrix 

and tuple of elements for the diagonal of a diagonal matrix. 

  

INPUT: 

  

- ``self`` - a matrix that is symmetric or Hermitian, 

over a ring that has a fraction field implemented. 

  

- ``algorithm`` - ``'symmetric'`` or ``'hermitian'``, 

according to the corresponding property of the matrix. 

  

- ``check`` - default: ``True`` - if ``True`` then 

performs the check that the matrix is consistent with the 

``algorithm`` keyword. 

  

OUTPUT: 

  

Given a square matrix ``A``, the routine returns a 

pair: a matrix ``L`` and a list ``d``. 

  

``L`` is a unit lower-triangular matrix. ``d`` is 

the entries of a diagonal matrix. Suppose this diagonal 

matrix is ``D``. Then, for a symmetric matrix, these items 

are related as: 

  

.. MATH:: 

  

A = LDL^T 

  

For a Hermitian matrix, the transpose can be replaced by 

the conjugate-transpose. 

  

If any leading principal submatrix is singular, then the 

computation cannot be performed and a ``ValueError`` results. 

  

Results are cached, and hence are immutable. Caching 

eliminates redundant computations across 

:meth:`indefinite_factorization_`, :meth:`is_positive_definite` 

and :meth:`cholesky_decomposition`. 

  

EXAMPLES: 

  

A simple symmetric matrix. :: 

  

sage: A = matrix(QQ, [[ 4, -2, 4, 2], 

....: [-2, 10, -2, -7], 

....: [ 4, -2, 8, 4], 

....: [ 2, -7, 4, 7]]) 

sage: A.is_symmetric() 

True 

sage: L, d = A._indefinite_factorization('symmetric') 

sage: L 

[ 1 0 0 0] 

[-1/2 1 0 0] 

[ 1 0 1 0] 

[ 1/2 -2/3 1/2 1] 

sage: d 

(4, 9, 4, 1) 

sage: A == L*diagonal_matrix(QQ, d)*L.transpose() 

True 

  

A Hermitian matrix. :: 

  

sage: x = var('x') 

sage: C.<I> = NumberField(x^2 + 1) 

sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I], 

....: [ -17*I + 3, 38, -69*I + 89, 7*I + 15], 

....: [-24*I + 25, 69*I + 89, 976, 24*I + 6], 

....: [ -21*I, -7*I + 15, -24*I + 6, 28]]) 

sage: A.is_hermitian() 

True 

sage: L, d = A._indefinite_factorization('hermitian') 

sage: L 

[ 1 0 0 0] 

[ -17/23*I + 3/23 1 0 0] 

[ -24/23*I + 25/23 617/288*I + 391/144 1 0] 

[ -21/23*I -49/288*I - 1/48 1336/89885*I - 773/89885 1] 

sage: d 

(23, 576/23, 89885/144, 142130/17977) 

sage: A == L*diagonal_matrix(C, d)*L.conjugate_transpose() 

True 

  

A matrix may have a singular submatrix in the upper-left 

corner ("a leading principal submatrix") which will unavoidably 

lead to division by zero. This is the only situation when this 

algorithm fails. :: 

  

sage: A = matrix(QQ, [[4, 6, 1], [6, 9, 5], [1, 5, 2]]) 

sage: B = A[0:2, 0:2]; B.determinant() 

0 

sage: A.indefinite_factorization(algorithm='symmetric') 

Traceback (most recent call last): 

... 

ValueError: 2x2 leading principal submatrix is singular, 

so cannot create indefinite factorization 

  

TESTS: 

  

The matrix must be square. :: 

  

sage: A = matrix(QQ, 3, 2, range(6)) 

sage: A._indefinite_factorization('symmetric') 

Traceback (most recent call last): 

... 

ValueError: matrix must be square, not 3 x 2 

  

The lone argument must describe the matrix. :: 

  

sage: A = matrix(QQ, [[1, 5], [5, 8]]) 

sage: A._indefinite_factorization('junk') 

Traceback (most recent call last): 

... 

ValueError: 'algorithm' must be 'symmetric' or 'hermitian', 

not junk 

  

The matrix must contain entries from an exact ring. :: 

  

sage: F = RealField(100) 

sage: A = matrix(F, [[1.0, 3.0], [3.0, -6.0]]) 

sage: A._indefinite_factorization('symmetric') 

Traceback (most recent call last): 

... 

TypeError: entries of the matrix must be in an exact ring, 

not Real Field with 100 bits of precision 

  

The base ring must have a fraction field. :: 

  

sage: A = matrix(Integers(6), [[1, 5], [5, 8]]) 

sage: A._indefinite_factorization('symmetric') 

Traceback (most recent call last): 

... 

TypeError: Unable to create the fraction field of 

Ring of integers modulo 6 

  

When ``check`` is ``True`` (the default), the matrix is 

checked to see if it conforms with the ``algorithm`` 

keyword. :: 

  

sage: A = matrix(QQ, 4, 4, range(16)) 

sage: A._indefinite_factorization('symmetric', check=True) 

Traceback (most recent call last): 

... 

ValueError: matrix is not symmetric (maybe try the 'hermitian' keyword) 

  

sage: A = matrix([[3, 2+3*I], [5+6*I, 12]]) 

sage: A._indefinite_factorization('hermitian', check=True) 

Traceback (most recent call last): 

... 

ValueError: matrix is not hermitian 

  

Results are cached and hence immutable, according 

to the ``algorithm``. :: 

  

sage: A = matrix(QQ, [[ 4, -2, 4, 2], 

....: [-2, 10, -2, -7], 

....: [ 4, -2, 8, 4], 

....: [ 2, -7, 4, 7]]) 

sage: Ls, ds = A._indefinite_factorization('symmetric') 

sage: Lh, dh = A._indefinite_factorization('hermitian') 

sage: Ls.is_immutable(), Lh.is_immutable() 

(True, True) 

sage: isinstance(ds, tuple), isinstance(dh, tuple) 

(True, True) 

  

We check that :trac:`16633` is fixed:: 

  

sage: A = matrix(QQ, [[ 4, -2, 4, 2], 

....: [-2, 10, -2, -7], 

....: [ 4, -2, 8, 4], 

....: [ 2, -7, 4, 7]]) 

sage: A.set_immutable() 

sage: L,d = A._indefinite_factorization('symmetric') 

sage: A 

[ 4 -2 4 2] 

[-2 10 -2 -7] 

[ 4 -2 8 4] 

[ 2 -7 4 7] 

  

AUTHOR: 

  

- Rob Beezer (2012-05-24) 

""" 

# Implementation note: L begins as a copy of self. 

# Entries below the diagonal are replaced as the loops proceed. 

# Entries above the diagonal are used to store entries of D*L^T, 

# which halves the number of multiplications needed otherwise. 

# The list d_inv holds reciprocals of the diagonal entries 

# So, below the diagonal, the main computation is: 

# A_ij = A_ij - (1/d_j)*sum(d_k*L_ik*L_jk, 0 <= k < j) 

  

cdef Py_ssize_t m, i, j, k 

cdef Matrix L 

  

if not algorithm in ['symmetric', 'hermitian']: 

msg = "'algorithm' must be 'symmetric' or 'hermitian', not {0}" 

raise ValueError(msg.format(algorithm)) 

cache_string = 'indefinite_factorization_' + algorithm 

factors = self.fetch(cache_string) 

if factors is None: 

R = self.base_ring() 

if not self.is_square(): 

msg = "matrix must be square, not {0} x {1}" 

raise ValueError(msg.format(self.nrows(), self.ncols())) 

if not algorithm in ['symmetric', 'hermitian']: 

msg = "'algorithm' must be 'symmetric' or 'hermitian', not {0}" 

raise ValueError(msg.format(algorithm)) 

if not R.is_exact(): 

msg = "entries of the matrix must be in an exact ring, not {0}" 

raise TypeError(msg.format(R)) 

try: 

F = R.fraction_field() 

except (NotImplementedError, TypeError): 

msg = 'Unable to create the fraction field of {0}' 

raise TypeError(msg.format(R)) 

if check and algorithm == 'symmetric': 

if not self.is_symmetric(): 

msg = "matrix is not symmetric (maybe try the 'hermitian' keyword)" 

raise ValueError(msg) 

if check and algorithm == 'hermitian': 

if not self.is_hermitian(): 

raise ValueError('matrix is not hermitian') 

conjugate = (algorithm == 'hermitian') 

# we need a copy no matter what, so we 

# (potentially) change to fraction field at the same time 

if R is F: 

L = self.__copy__() 

else: 

L = self.change_ring(F) 

  

m = L._nrows 

zero = F.zero() 

one = F.one() 

d = [] 

d_inv = [] 

for i in range(m): 

for j in range(i+1): 

t = L.get_unsafe(i, j) 

if conjugate: 

for k in range(j): 

t -= L.get_unsafe(k,i)*L.get_unsafe(j,k).conjugate() 

else: 

for k in range(j): 

t -= L.get_unsafe(k,i)*L.get_unsafe(j,k) 

if i == j: 

if not t: 

self.cache(cache_string, (False,i+1)) 

return (False, i+1) 

d.append(t) 

d_inv.append(one/t) 

L.set_unsafe(i, i, one) 

else: 

L.set_unsafe(j, i, t) 

L.set_unsafe(i, j, (d_inv[j] * t)) 

# Triangularize output matrix 

for i in range(m): 

for j in range(i+1, m): 

L.set_unsafe(i, j, zero) 

L.set_immutable() 

factors = (L, tuple(d)) 

self.cache(cache_string, factors) 

return factors 

  

def indefinite_factorization(self, algorithm='symmetric', check=True): 

r""" 

Decomposes a symmetric or Hermitian matrix into a 

lower triangular matrix and a diagonal matrix. 

  

INPUT: 

  

- ``self`` - a square matrix over a ring. The base ring 

must have an implemented fraction field. 

  

- ``algorithm`` - default: ``'symmetric'``. Either 

``'symmetric'`` or ``'hermitian'``, according to if 

the input matrix is symmetric or hermitian. 

  

- ``check`` - default: ``True`` - if ``True`` then 

performs the check that the matrix is consistent with the 

``algorithm`` keyword. 

  

OUTPUT: 

  

A lower triangular matrix `L` with each diagonal element 

equal to `1` and a vector of entries that form a 

diagonal matrix `D`. The vector of diagonal entries 

can be easily used to form the matrix, as demonstrated 

below in the examples. 

  

For a symmetric matrix, `A`, these will be related by 

  

.. MATH:: 

  

A = LDL^T 

  

If `A` is Hermitian matrix, then the transpose of `L` 

should be replaced by the conjugate-transpose of `L`. 

  

If any leading principal submatrix (a square submatrix 

in the upper-left corner) is singular then this method will 

fail with a ``ValueError``. 

  

ALGORITHM: 

  

The algorithm employed only uses field operations, 

but the computation of each diagonal entry has the potential 

for division by zero. The number of operations is of order 

`n^3/3`, which is half the count for an LU decomposition. 

This makes it an appropriate candidate for solving systems 

with symmetric (or Hermitian) coefficient matrices. 

  

EXAMPLES: 

  

There is no requirement that a matrix be positive definite, as 

indicated by the negative entries in the resulting diagonal 

matrix. The default is that the input matrix is symmetric. :: 

  

sage: A = matrix(QQ, [[ 3, -6, 9, 6, -9], 

....: [-6, 11, -16, -11, 17], 

....: [ 9, -16, 28, 16, -40], 

....: [ 6, -11, 16, 9, -19], 

....: [-9, 17, -40, -19, 68]]) 

sage: A.is_symmetric() 

True 

sage: L, d = A.indefinite_factorization() 

sage: D = diagonal_matrix(d) 

sage: L 

[ 1 0 0 0 0] 

[-2 1 0 0 0] 

[ 3 -2 1 0 0] 

[ 2 -1 0 1 0] 

[-3 1 -3 1 1] 

sage: D 

[ 3 0 0 0 0] 

[ 0 -1 0 0 0] 

[ 0 0 5 0 0] 

[ 0 0 0 -2 0] 

[ 0 0 0 0 -1] 

sage: A == L*D*L.transpose() 

True 

  

Optionally, Hermitian matrices can be factored 

and the result has a similar property (but not 

identical). Here, the field is all complex numbers 

with rational real and imaginary parts. As theory 

predicts, the diagonal entries will be real numbers. :: 

  

sage: C.<I> = QuadraticField(-1) 

sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I], 

....: [4 + 2*I, 8, 10*I], 

....: [2 - 2*I, -10*I, -3]]) 

sage: B.is_hermitian() 

True 

sage: L, d = B.indefinite_factorization(algorithm='hermitian') 

sage: D = diagonal_matrix(d) 

sage: L 

[ 1 0 0] 

[ I + 2 1 0] 

[ -I + 1 2*I + 1 1] 

sage: D 

[ 2 0 0] 

[ 0 -2 0] 

[ 0 0 3] 

sage: B == L*D*L.conjugate_transpose() 

True 

  

If a leading principal submatrix has zero determinant, this 

algorithm will fail. This will never happen with a positive 

definite matrix. :: 

  

sage: A = matrix(QQ, [[21, 15, 12, -2], 

....: [15, 12, 9, 6], 

....: [12, 9, 7, 3], 

....: [-2, 6, 3, 8]]) 

sage: A.is_symmetric() 

True 

sage: A[0:3,0:3].det() == 0 

True 

sage: A.indefinite_factorization() 

Traceback (most recent call last): 

... 

ValueError: 3x3 leading principal submatrix is singular, 

so cannot create indefinite factorization 

  

This algorithm only depends on field operations, so 

outside of the singular submatrix situation, any matrix 

may be factored. This provides a reasonable alternative 

to the Cholesky decomposition. :: 

  

sage: F.<a> = FiniteField(5^3) 

sage: A = matrix(F, 

....: [[ a^2 + 2*a, 4*a^2 + 3*a + 4, 3*a^2 + a, 2*a^2 + 2*a + 1], 

....: [4*a^2 + 3*a + 4, 4*a^2 + 2, 3*a, 2*a^2 + 4*a + 2], 

....: [ 3*a^2 + a, 3*a, 3*a^2 + 2, 3*a^2 + 2*a + 3], 

....: [2*a^2 + 2*a + 1, 2*a^2 + 4*a + 2, 3*a^2 + 2*a + 3, 3*a^2 + 2*a + 4]]) 

sage: A.is_symmetric() 

True 

sage: L, d = A.indefinite_factorization() 

sage: D = diagonal_matrix(d) 

sage: L 

[ 1 0 0 0] 

[4*a^2 + 4*a + 3 1 0 0] 

[ 3 4*a^2 + a + 2 1 0] 

[ 4*a^2 + 4 2*a^2 + 3*a + 3 2*a^2 + 3*a + 1 1] 

sage: D 

[ a^2 + 2*a 0 0 0] 

[ 0 2*a^2 + 2*a + 4 0 0] 

[ 0 0 3*a^2 + 4*a + 3 0] 

[ 0 0 0 a^2 + 3*a] 

sage: A == L*D*L.transpose() 

True 

  

This works correctly for the 0x0 matrix:: 

  

sage: Matrix(0).indefinite_factorization() 

([], ()) 

  

AUTHOR: 

  

- Rob Beezer (2012-05-24) 

""" 

from sage.modules.free_module_element import vector 

L, d = self._indefinite_factorization(algorithm, check=check) 

if L is False: 

msg = "{0}x{0} leading principal submatrix is singular, so cannot create indefinite factorization" 

raise ValueError(msg.format(d)) 

return L, vector(L.base_ring(), d) 

  

def is_positive_definite(self): 

r""" 

Determines if a real or symmetric matrix is positive definite. 

  

A square matrix `A` is positive definite if it is 

symmetric with real entries or Hermitian with complex entries, 

and for every non-zero vector `\vec{x}` 

  

.. MATH:: 

  

\vec{x}^\ast A\vec{x} > 0 

  

Here `\vec{x}^\ast` is the conjugate-transpose, which can be 

simplified to just the transpose in the real case. 

  

ALGORITHM: 

  

A matrix is positive definite if and only if the 

diagonal entries from the indefinite factorization 

are all positive (see :meth:`indefinite_factorization`). 

So this algorithm is of order ``n^3/3`` and may be applied 

to matrices with elements of any ring that has a fraction 

field contained within the reals or complexes. 

  

INPUT: 

  

Any square matrix. 

  

OUTPUT: 

  

This routine will return ``True`` if the matrix is square, 

symmetric or Hermitian, and meets the condition above 

for the quadratic form. 

  

The base ring for the elements of the matrix needs to 

have a fraction field implemented and the computations 

that result from the indefinite factorization must be 

convertable to real numbers that are comparable to zero. 

  

EXAMPLES: 

  

A real symmetric matrix that is positive definite, 

as evidenced by the positive entries for the diagonal 

matrix of the indefinite factorization and the positive 

determinants of the leading principal submatrices. :: 

  

sage: A = matrix(QQ, [[ 4, -2, 4, 2], 

....: [-2, 10, -2, -7], 

....: [ 4, -2, 8, 4], 

....: [ 2, -7, 4, 7]]) 

sage: A.is_positive_definite() 

True 

sage: _, d = A.indefinite_factorization(algorithm='symmetric') 

sage: d 

(4, 9, 4, 1) 

sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)] 

[4, 36, 144, 144] 

  

A real symmetric matrix which is not positive definite, along 

with a vector that makes the quadratic form negative. :: 

  

sage: A = matrix(QQ, [[ 3, -6, 9, 6, -9], 

....: [-6, 11, -16, -11, 17], 

....: [ 9, -16, 28, 16, -40], 

....: [ 6, -11, 16, 9, -19], 

....: [-9, 17, -40, -19, 68]]) 

sage: A.is_positive_definite() 

False 

sage: _, d = A.indefinite_factorization(algorithm='symmetric') 

sage: d 

(3, -1, 5, -2, -1) 

sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)] 

[3, -3, -15, 30, -30] 

sage: u = vector(QQ, [2, 2, 0, 1, 0]) 

sage: u.row()*A*u 

(-3) 

  

A real symmetric matrix with a singular leading 

principal submatrix, that is therefore not positive definite. 

The vector ``u`` makes the quadratic form zero. :: 

  

sage: A = matrix(QQ, [[21, 15, 12, -2], 

....: [15, 12, 9, 6], 

....: [12, 9, 7, 3], 

....: [-2, 6, 3, 8]]) 

sage: A.is_positive_definite() 

False 

sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)] 

[21, 27, 0, -75] 

sage: u = vector(QQ, [1,1,-3,0]) 

sage: u.row()*A*u 

(0) 

  

An Hermitian matrix that is positive definite. :: 

  

sage: C.<I> = NumberField(x^2 + 1, embedding=CC(0,1)) 

sage: A = matrix(C, [[ 23, 17*I + 3, 24*I + 25, 21*I], 

....: [ -17*I + 3, 38, -69*I + 89, 7*I + 15], 

....: [-24*I + 25, 69*I + 89, 976, 24*I + 6], 

....: [ -21*I, -7*I + 15, -24*I + 6, 28]]) 

sage: A.is_positive_definite() 

True 

sage: _, d = A.indefinite_factorization(algorithm='hermitian') 

sage: d 

(23, 576/23, 89885/144, 142130/17977) 

sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)] 

[23, 576, 359540, 2842600] 

  

An Hermitian matrix that is not positive definite. 

The vector ``u`` makes the quadratic form negative. :: 

  

sage: C.<I> = QuadraticField(-1) 

sage: B = matrix(C, [[ 2, 4 - 2*I, 2 + 2*I], 

....: [4 + 2*I, 8, 10*I], 

....: [2 - 2*I, -10*I, -3]]) 

sage: B.is_positive_definite() 

False 

sage: _, d = B.indefinite_factorization(algorithm='hermitian') 

sage: d 

(2, -2, 3) 

sage: [B[:i,:i].determinant() for i in range(1,B.nrows()+1)] 

[2, -4, -12] 

sage: u = vector(C, [-5 + 10*I, 4 - 3*I, 0]) 

sage: u.row().conjugate()*B*u 

(-50) 

  

A positive definite matrix over an algebraically closed field. :: 

  

sage: A = matrix(QQbar, [[ 2, 4 + 2*I, 6 - 4*I], 

....: [ -2*I + 4, 11, 10 - 12*I], 

....: [ 4*I + 6, 10 + 12*I, 37]]) 

sage: A.is_positive_definite() 

True 

sage: [A[:i,:i].determinant() for i in range(1,A.nrows()+1)] 

[2, 2, 6] 

  

TESTS: 

  

If the base ring lacks a ``conjugate`` method, it 

will be assumed to not be Hermitian and thus symmetric. 

If the base ring does not make sense as a subfield of 

the reals, then this routine will fail since comparison 

to zero is meaningless. :: 

  

sage: F.<a> = FiniteField(5^3) 

sage: a.conjugate() 

Traceback (most recent call last): 

... 

AttributeError: 'sage.rings.finite_rings.element_givaro.FiniteField_givaroElement' 

object has no attribute 'conjugate' 

sage: A = matrix(F, 

....: [[ a^2 + 2*a, 4*a^2 + 3*a + 4, 3*a^2 + a, 2*a^2 + 2*a + 1], 

....: [4*a^2 + 3*a + 4, 4*a^2 + 2, 3*a, 2*a^2 + 4*a + 2], 

....: [ 3*a^2 + a, 3*a, 3*a^2 + 2, 3*a^2 + 2*a + 3], 

....: [2*a^2 + 2*a + 1, 2*a^2 + 4*a + 2, 3*a^2 + 2*a + 3, 3*a^2 + 2*a + 4]]) 

sage: A.is_positive_definite() 

Traceback (most recent call last): 

... 

ValueError: Could not see Finite Field in a of size 5^3 as a subring 

of the real or complex numbers 

  

The 0x0 matrix is trivially positive definite:: 

  

sage: Matrix(0).is_positive_definite() 

True 

  

AUTHOR: 

  

- Rob Beezer (2012-05-24) 

""" 

from sage.rings.real_lazy import RLF,CLF 

  

R = self.base_ring() 

if RLF.has_coerce_map_from(R): 

if not self.is_symmetric(): 

return False 

L, d = self._indefinite_factorization('symmetric', check=False) 

real = True 

elif CLF.has_coerce_map_from(R): 

if not self.is_hermitian(): 

return False 

L, d = self._indefinite_factorization('hermitian', check=False) 

real = False 

else: 

raise ValueError("Could not see {} as a subring of the " 

"real or complex numbers".format(R)) 

  

if L is False: 

return False 

  

# Now have diagonal entries (hopefully real) and so can 

# test with a generator (which will short-circuit) 

# positive definite iff all entries of d are positive 

zero = R.fraction_field().zero() 

if real: 

return all(x > zero for x in d) 

else: 

return all(x.real() > zero for x in d) 

  

def hadamard_bound(self): 

r""" 

Return an int n such that the absolute value of the determinant of 

this matrix is at most `10^n`. 

  

This is got using both the row norms and the column norms. 

  

This function only makes sense when the base field can be coerced 

to the real double field RDF or the MPFR Real Field with 53-bits 

precision. 

  

EXAMPLES:: 

  

sage: a = matrix(ZZ, 3, [1,2,5,7,-3,4,2,1,123]) 

sage: a.hadamard_bound() 

4 

sage: a.det() 

-2014 

sage: 10^4 

10000 

  

In this example the Hadamard bound has to be computed 

(automatically) using MPFR instead of doubles, since doubles 

overflow:: 

  

sage: a = matrix(ZZ, 2, [2^10000,3^10000,2^50,3^19292]) 

sage: a.hadamard_bound() 

12215 

sage: len(str(a.det())) 

12215 

""" 

from sage.rings.all import RDF, RealField 

try: 

A = self.change_ring(RDF) 

m1 = A._hadamard_row_bound() 

A = A.transpose() 

m2 = A._hadamard_row_bound() 

return min(m1, m2) 

except (OverflowError, TypeError): 

# Try using MPFR, which handles large numbers much better, but is slower. 

from . import misc 

R = RealField(53, rnd='RNDU') 

A = self.change_ring(R) 

m1 = misc.hadamard_row_bound_mpfr(A) 

A = A.transpose() 

m2 = misc.hadamard_row_bound_mpfr(A) 

return min(m1, m2) 

  

def find(self,f, indices=False): 

r""" 

Find elements in this matrix satisfying the constraints in the 

function `f`. The function is evaluated on each element of 

the matrix . 

  

INPUT: 

  

  

- ``f`` - a function that is evaluated on each 

element of this matrix. 

  

- ``indices`` - whether or not to return the indices 

and elements of this matrix that satisfy the function. 

  

  

OUTPUT: If ``indices`` is not specified, return a 

matrix with 1 where `f` is satisfied and 0 where it is not. 

If ``indices`` is specified, return a dictionary 

containing the elements of this matrix satisfying `f`. 

  

EXAMPLES:: 

  

sage: M = matrix(4,3,[1, -1/2, -1, 1, -1, -1/2, -1, 0, 0, 2, 0, 1]) 

sage: M.find(lambda entry:entry==0) 

[0 0 0] 

[0 0 0] 

[0 1 1] 

[0 1 0] 

  

:: 

  

sage: M.find(lambda u:u<0) 

[0 1 1] 

[0 1 1] 

[1 0 0] 

[0 0 0] 

  

:: 

  

sage: M = matrix(4,3,[1, -1/2, -1, 1, -1, -1/2, -1, 0, 0, 2, 0, 1]) 

sage: len(M.find(lambda u:u<1 and u>-1,indices=True)) 

5 

  

:: 

  

sage: M.find(lambda u:u!=1/2) 

[1 1 1] 

[1 1 1] 

[1 1 1] 

[1 1 1] 

  

:: 

  

sage: M.find(lambda u:u>1.2) 

[0 0 0] 

[0 0 0] 

[0 0 0] 

[1 0 0] 

  

:: 

  

sage: sorted(M.find(lambda u:u!=0,indices=True).keys()) == M.nonzero_positions() 

True 

""" 

from sage.matrix.matrix_space import MatrixSpace 

cdef Py_ssize_t size,i,j 

cdef object M 

  

if not indices: 

L = self._list() 

size = PyList_GET_SIZE(L) 

M = PyList_New(0) 

  

for i from 0 <= i < size: 

PyList_Append(M,<object>f(<object>PyList_GET_ITEM(L,i))) 

  

return MatrixSpace(IntegerModRing(2), 

nrows=self._nrows,ncols=self._ncols).matrix(M) 

  

else: 

# return matrix along with indices in a dictionary 

d = {} 

for i from 0 <= i < self._nrows: 

for j from 0 <= j < self._ncols: 

if f(self.get_unsafe(i,j)): 

d[(i,j)] = self.get_unsafe(i,j) 

  

return d 

  

def conjugate(self): 

r""" 

Return the conjugate of self, i.e. the matrix whose entries are the 

conjugates of the entries of self. 

  

EXAMPLES:: 

  

sage: A = matrix(CDF, [[1+I,1],[0,2*I]]) 

sage: A.conjugate() 

[1.0 - 1.0*I 1.0] 

[ 0.0 -2.0*I] 

  

A matrix over a not-totally-real number field:: 

  

sage: K.<j> = NumberField(x^2+5) 

sage: M = matrix(K, [[1+j,1], [0,2*j]]) 

sage: M.conjugate() 

[-j + 1 1] 

[ 0 -2*j] 

  

There is a shortcut for the conjugate:: 

  

sage: M.C 

[-j + 1 1] 

[ 0 -2*j] 

  

There is also a shortcut for the conjugate transpose, or "Hermitian transpose":: 

  

sage: M.H 

[-j + 1 0] 

[ 1 -2*j] 

  

Conjugates work (trivially) for matrices over rings that embed 

canonically into the real numbers:: 

  

sage: M = random_matrix(ZZ, 2) 

sage: M == M.conjugate() 

True 

sage: M = random_matrix(QQ, 3) 

sage: M == M.conjugate() 

True 

sage: M = random_matrix(RR, 2) 

sage: M == M.conjugate() 

True 

""" 

return self.new_matrix(self.nrows(), self.ncols(), [z.conjugate() for z in self.list()]) 

  

def conjugate_transpose(self): 

r""" 

Returns the transpose of ``self`` after each entry has been converted to its complex conjugate. 

  

.. NOTE:: 

This function is sometimes known as the "adjoint" of a matrix, 

though there is substantial variation and some confusion with 

the use of that term. 

  

OUTPUT: 

  

A matrix formed by taking the complex conjugate of every entry 

of ``self`` and then transposing the resulting matrix. 

  

Complex conjugation is implemented for many subfields 

of the complex numbers. See the examples below, or more 

at :meth:`~conjugate`. 

  

EXAMPLES:: 

  

sage: M = matrix(SR, 2, 2, [[2-I, 3+4*I], [9-6*I, 5*I]]) 

sage: M.base_ring() 

Symbolic Ring 

sage: M.conjugate_transpose() 

[ I + 2 6*I + 9] 

[-4*I + 3 -5*I] 

  

sage: P = matrix(CC, 3, 2, [0.95-0.63*I, 0.84+0.13*I, 0.94+0.23*I, 0.23+0.59*I, 0.52-0.41*I, -0.50+0.90*I]) 

sage: P.base_ring() 

Complex Field with 53 bits of precision 

sage: P.conjugate_transpose() 

[ 0.950... + 0.630...*I 0.940... - 0.230...*I 0.520... + 0.410...*I] 

[ 0.840... - 0.130...*I 0.230... - 0.590...*I -0.500... - 0.900...*I] 

  

There is also a shortcut for the conjugate transpose, or "Hermitian transpose":: 

  

sage: M.H 

[ I + 2 6*I + 9] 

[-4*I + 3 -5*I] 

  

Matrices over base rings that can be embedded in the 

real numbers will behave as expected. :: 

  

sage: P = random_matrix(QQ, 3, 4) 

sage: P.conjugate_transpose() == P.transpose() 

True 

  

The conjugate of a matrix is formed by taking conjugates of 

all the entries. Some specialized subfields of the complex numbers 

are implemented in Sage and complex conjugation can be applied. 

(Matrices over quadratic number fields are another 

class of examples.) :: 

  

sage: C = CyclotomicField(5) 

sage: a = C.gen(); a 

zeta5 

sage: CC(a) 

0.309016994374947 + 0.951056516295154*I 

sage: M = matrix(C, 1, 2, [a^2, a+a^3]) 

sage: M.conjugate_transpose() 

[ zeta5^3] 

[-zeta5^3 - zeta5 - 1] 

  

Conjugation does not make sense over rings not containing complex numbers. :: 

  

sage: N = matrix(GF(5), 2, [0,1,2,3]) 

sage: N.conjugate_transpose() 

Traceback (most recent call last): 

... 

AttributeError: 'sage.rings.finite_rings.integer_mod.IntegerMod_int' object has no attribute 'conjugate' 

  

AUTHOR: 

  

Rob Beezer (2010-12-13) 

""" 

# limited testing on a 1000 x 1000 matrix over CC: 

# transpose is fast, conjugate is slow 

# so perhaps direct speed improvements to the conjugate() method 

return self.conjugate().transpose() 

  

def norm(self, p=2): 

r""" 

Return the p-norm of this matrix, where `p` can be 1, 2, 

`\inf`, or the Frobenius norm. 

  

INPUT: 

  

  

- ``self`` - a matrix whose entries are coercible into 

CDF 

  

- ``p`` - one of the following options: 

  

- ``1`` - the largest column-sum norm 

  

- ``2 (default)`` - the Euclidean norm 

  

- ``Infinity`` - the largest row-sum norm 

  

- ``'frob'`` - the Frobenius (sum of squares) norm 

  

  

OUTPUT: RDF number 

  

.. SEEALSO:: 

  

- :func:`sage.misc.functional.norm` 

  

EXAMPLES:: 

  

sage: A = matrix(ZZ, [[1,2,4,3],[-1,0,3,-10]]) 

sage: A.norm(1) 

13.0 

sage: A.norm(Infinity) 

14.0 

sage: B = random_matrix(QQ, 20, 21) 

sage: B.norm(Infinity) == (B.transpose()).norm(1) 

True 

  

:: 

  

sage: Id = identity_matrix(12) 

sage: Id.norm(2) 

1.0 

sage: A = matrix(RR, 2, 2, [13,-4,-4,7]) 

sage: A.norm() # rel tol 2e-16 

14.999999999999998 

  

Norms of numerical matrices over high-precision reals are computed by this routine. 

Faster routines for double precision entries from `RDF` or `CDF` are provided by 

the :class:`~sage.matrix.matrix_double_dense.Matrix_double_dense` class. :: 

  

sage: A = matrix(CC, 2, 3, [3*I,4,1-I,1,2,0]) 

sage: A.norm('frob') 

5.656854249492381 

sage: A.norm(2) 

5.470684443210... 

sage: A.norm(1) 

6.0 

sage: A.norm(Infinity) 

8.414213562373096 

sage: a = matrix([[],[],[],[]]) 

sage: a.norm() 

0.0 

sage: a.norm(Infinity) == a.norm(1) 

True 

""" 

  

if self._nrows == 0 or self._ncols == 0: 

return RDF(0) 

  

# 2-norm: 

if p == 2: 

A = self.change_ring(CDF) 

A = A.conjugate().transpose() * A 

U, S, V = A.SVD() 

return max(S.list()).real().sqrt() 

  

A = self.apply_map(abs).change_ring(RDF) 

  

# 1-norm: largest column-sum 

if p == 1: 

A = A.transpose() 

return max([sum(i) for i in list(A)]) 

  

# Infinity norm: largest row-sum 

if p == sage.rings.infinity.Infinity: 

return max([sum(i) for i in list(A)]) 

  

# Frobenius norm: square root of sum of squares of entries of self 

if p == 'frob': 

return sum([i**2 for i in A.list()]).sqrt() 

  

def numerical_approx(self, prec=None, digits=None, algorithm=None): 

r""" 

Return a numerical approximation of ``self`` with ``prec`` bits 

(or decimal ``digits``) of precision. 

  

INPUT: 

  

- ``prec`` -- precision in bits 

  

- ``digits`` -- precision in decimal digits (only used if 

``prec`` is not given) 

  

- ``algorithm`` -- ignored for matrices 

  

OUTPUT: A matrix converted to a real or complex field 

  

EXAMPLES:: 

  

sage: d = matrix([[3, 0],[0,sqrt(2)]]) ; 

sage: b = matrix([[1, -1], [2, 2]]) ; e = b * d * b.inverse();e 

[ 1/2*sqrt(2) + 3/2 -1/4*sqrt(2) + 3/4] 

[ -sqrt(2) + 3 1/2*sqrt(2) + 3/2] 

  

:: 

  

sage: e.numerical_approx(53) 

[ 2.20710678118655 0.396446609406726] 

[ 1.58578643762690 2.20710678118655] 

  

:: 

  

sage: e.numerical_approx(20) 

[ 2.2071 0.39645] 

[ 1.5858 2.2071] 

  

:: 

  

sage: (e-I).numerical_approx(20) 

[2.2071 - 1.0000*I 0.39645] 

[ 1.5858 2.2071 - 1.0000*I] 

  

:: 

  

sage: M=matrix(QQ,4,[i/(i+1) for i in range(12)]);M 

[ 0 1/2 2/3] 

[ 3/4 4/5 5/6] 

[ 6/7 7/8 8/9] 

[ 9/10 10/11 11/12] 

  

:: 

  

sage: M.numerical_approx() 

[0.000000000000000 0.500000000000000 0.666666666666667] 

[0.750000000000000 0.800000000000000 0.833333333333333] 

[0.857142857142857 0.875000000000000 0.888888888888889] 

[0.900000000000000 0.909090909090909 0.916666666666667] 

  

:: 

  

sage: matrix(SR, 2, 2, range(4)).n() 

[0.000000000000000 1.00000000000000] 

[ 2.00000000000000 3.00000000000000] 

  

:: 

  

sage: numerical_approx(M) 

[0.000000000000000 0.500000000000000 0.666666666666667] 

[0.750000000000000 0.800000000000000 0.833333333333333] 

[0.857142857142857 0.875000000000000 0.888888888888889] 

[0.900000000000000 0.909090909090909 0.916666666666667] 

""" 

if prec is None: 

prec = digits_to_bits(digits) 

  

try: 

return self.change_ring(sage.rings.real_mpfr.RealField(prec)) 

except TypeError: 

# try to return a complex result 

return self.change_ring(sage.rings.complex_field.ComplexField(prec)) 

  

def plot(self, *args, **kwds): 

""" 

A plot of this matrix. 

  

Each (ith, jth) matrix element is given a different color value 

depending on its relative size compared to the other elements in 

the matrix. 

  

The tick marks drawn on the frame axes denote the (ith, jth) 

element of the matrix. 

  

This method just calls ``matrix_plot``. 

``*args`` and ``**kwds`` are passed to 

``matrix_plot``. 

  

EXAMPLES: 

  

A matrix over ZZ colored with different grey levels:: 

  

sage: A = matrix([[1,3,5,1],[2,4,5,6],[1,3,5,7]]) 

sage: A.plot() 

Graphics object consisting of 1 graphics primitive 

  

Here we make a random matrix over RR and use cmap='hsv' to color 

the matrix elements different RGB colors (see documentation for 

``matrix_plot`` for more information on cmaps):: 

  

sage: A = random_matrix(RDF, 50) 

sage: plot(A, cmap='hsv') 

Graphics object consisting of 1 graphics primitive 

  

Another random plot, but over GF(389):: 

  

sage: A = random_matrix(GF(389), 10) 

sage: A.plot(cmap='Oranges') 

Graphics object consisting of 1 graphics primitive 

""" 

from sage.plot.plot import matrix_plot 

return matrix_plot(self, *args, **kwds) 

  

def derivative(self, *args): 

""" 

Derivative with respect to variables supplied in args. 

  

Multiple variables and iteration counts may be supplied; see 

documentation for the global derivative() function for more 

details. 

  

EXAMPLES:: 

  

sage: v = vector([1,x,x^2]) 

sage: v.derivative(x) 

(0, 1, 2*x) 

sage: type(v.derivative(x)) == type(v) 

True 

sage: v = vector([1,x,x^2], sparse=True) 

sage: v.derivative(x) 

(0, 1, 2*x) 

sage: type(v.derivative(x)) == type(v) 

True 

sage: v.derivative(x,x) 

(0, 0, 2) 

""" 

return multi_derivative(self, args) 

  

def exp(self): 

r""" 

Calculate the exponential of this matrix X, which is the matrix 

  

.. MATH:: 

  

e^X = \sum_{k=0}^{\infty} \frac{X^k}{k!}. 

  

This function depends on maxima's matrix exponentiation 

function, which does not deal well with floating point 

numbers. If the matrix has floating point numbers, they will 

be rounded automatically to rational numbers during the 

computation. If you want approximations to the exponential 

that are calculated numerically, you may get better results by 

first converting your matrix to RDF or CDF, as shown in the 

last example. 

  

EXAMPLES:: 

  

sage: a=matrix([[1,2],[3,4]]) 

sage: a.exp() 

[-1/22*((sqrt(33) - 11)*e^sqrt(33) - sqrt(33) - 11)*e^(-1/2*sqrt(33) + 5/2) 2/33*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2)] 

[ 1/11*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2) 1/22*((sqrt(33) + 11)*e^sqrt(33) - sqrt(33) + 11)*e^(-1/2*sqrt(33) + 5/2)] 

  

sage: type(a.exp()) 

<type 'sage.matrix.matrix_symbolic_dense.Matrix_symbolic_dense'> 

  

sage: a=matrix([[1/2,2/3],[3/4,4/5]]) 

sage: a.exp() 

[-1/418*((3*sqrt(209) - 209)*e^(1/10*sqrt(209)) - 3*sqrt(209) - 209)*e^(-1/20*sqrt(209) + 13/20) 20/627*(sqrt(209)*e^(1/10*sqrt(209)) - sqrt(209))*e^(-1/20*sqrt(209) + 13/20)] 

[ 15/418*(sqrt(209)*e^(1/10*sqrt(209)) - sqrt(209))*e^(-1/20*sqrt(209) + 13/20) 1/418*((3*sqrt(209) + 209)*e^(1/10*sqrt(209)) - 3*sqrt(209) + 209)*e^(-1/20*sqrt(209) + 13/20)] 

  

sage: a=matrix(RR,[[1,pi.n()],[1e2,1e-2]]) 

sage: a.exp() 

[ 1/11882424341266*((11*sqrt(227345670387496707609) + 5941212170633)*e^(3/1275529100*sqrt(227345670387496707609)) - 11*sqrt(227345670387496707609) + 5941212170633)*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200) 445243650/75781890129165569203*(sqrt(227345670387496707609)*e^(3/1275529100*sqrt(227345670387496707609)) - sqrt(227345670387496707609))*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200)] 

[ 10000/53470909535697*(sqrt(227345670387496707609)*e^(3/1275529100*sqrt(227345670387496707609)) - sqrt(227345670387496707609))*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200) -1/11882424341266*((11*sqrt(227345670387496707609) - 5941212170633)*e^(3/1275529100*sqrt(227345670387496707609)) - 11*sqrt(227345670387496707609) - 5941212170633)*e^(-3/2551058200*sqrt(227345670387496707609) + 101/200)] 

sage: a.change_ring(RDF).exp() # rel tol 1e-14 

[42748127.31532951 7368259.244159399] 

[234538976.1381042 40426191.45156228] 

""" 

from sage.symbolic.ring import SR 

return self.change_ring(SR).exp() 

  

def elementary_divisors(self): 

r""" 

If self is a matrix over a principal ideal domain R, return 

elements `d_i` for `1 \le i \le k = \min(r,s)` 

where `r` and `s` are the number of rows and 

columns of self, such that the cokernel of self is isomorphic to 

  

.. MATH:: 

  

R/(d_1) \oplus R/(d_2) \oplus R/(d_k) 

  

with `d_i \mid d_{i+1}` for all `i`. These are 

the diagonal entries of the Smith form of self (see 

:meth:`smith_form()`). 

  

EXAMPLES:: 

  

sage: OE.<w> = EquationOrder(x^2 - x + 2) 

sage: m = Matrix([ [1, w],[w,7]]) 

sage: m.elementary_divisors() 

[1, -w + 9] 

  

.. SEEALSO:: 

  

:meth:`smith_form` 

""" 

d, u, v = self.smith_form() 

r = min(self.nrows(), self.ncols()) 

return [d[i,i] for i in xrange(r)] 

  

def smith_form(self): 

r""" 

If self is a matrix over a principal ideal domain R, return 

matrices D, U, V over R such that D = U \* self \* V, U and V have 

unit determinant, and D is diagonal with diagonal entries the 

ordered elementary divisors of self, ordered so that 

`D_{i} \mid D_{i+1}`. Note that U and V are not uniquely 

defined in general, and D is defined only up to units. 

  

INPUT: 

  

  

- ``self`` - a matrix over an integral domain. If the 

base ring is not a PID, the routine might work, or else it will 

fail having found an example of a non-principal ideal. Note that we 

do not call any methods to check whether or not the base ring is a 

PID, since this might be quite expensive (e.g. for rings of 

integers of number fields of large degree). 

  

  

ALGORITHM: Lifted wholesale from :wikipedia:`Smith_normal_form` 

  

.. SEEALSO:: 

  

:meth:`elementary_divisors` 

  

AUTHORS: 

  

- David Loeffler (2008-12-05) 

  

EXAMPLES: 

  

An example over the ring of integers of a number field (of class 

number 1):: 

  

sage: OE.<w> = EquationOrder(x^2 - x + 2) 

sage: m = Matrix([ [1, w],[w,7]]) 

sage: d, u, v = m.smith_form() 

sage: (d, u, v) 

( 

[ 1 0] [ 1 0] [ 1 -w] 

[ 0 -w + 9], [-w 1], [ 0 1] 

) 

sage: u * m * v == d 

True 

sage: u.base_ring() == v.base_ring() == d.base_ring() == OE 

True 

sage: u.det().is_unit() and v.det().is_unit() 

True 

  

An example over the polynomial ring QQ[x]:: 

  

sage: R.<x> = QQ[]; m=x*matrix(R,2,2,1) - matrix(R, 2,2,[3,-4,1,-1]); m.smith_form() 

( 

[ 1 0] [ 0 -1] [ 1 x + 1] 

[ 0 x^2 - 2*x + 1], [ 1 x - 3], [ 0 1] 

) 

  

An example over a field:: 

  

sage: m = matrix( GF(17), 3, 3, [11,5,1,3,6,8,1,16,0]); d,u,v = m.smith_form() 

sage: d 

[1 0 0] 

[0 1 0] 

[0 0 0] 

sage: u*m*v == d 

True 

  

Some examples over non-PID's work anyway:: 

  

sage: R.<s> = EquationOrder(x^2 + 5) # class number 2 

sage: A = matrix(R, 2, 2, [s-1,-s,-s,2*s+1]) 

sage: D, U, V = A.smith_form() 

sage: D, U, V 

( 

[ 1 0] [ 4 s + 4] [ 1 -5*s + 6] 

[ 0 -s - 6], [ s s - 1], [ 0 1] 

) 

sage: D == U*A*V 

True 

  

Others don't, but they fail quite constructively:: 

  

sage: matrix(R,2,2,[s-1,-s-2,-2*s,-s-2]).smith_form() 

Traceback (most recent call last): 

... 

ArithmeticError: Ideal Fractional ideal (2, s + 1) not principal 

  

Empty matrices are handled safely:: 

  

sage: m = MatrixSpace(OE, 2,0)(0); d,u,v=m.smith_form(); u*m*v == d 

True 

sage: m = MatrixSpace(OE, 0,2)(0); d,u,v=m.smith_form(); u*m*v == d 

True 

sage: m = MatrixSpace(OE, 0,0)(0); d,u,v=m.smith_form(); u*m*v == d 

True 

  

Some pathological cases that crashed earlier versions:: 

  

sage: m = Matrix(OE, [[2*w,2*w-1,-w+1],[2*w+2,-2*w-1,w-1],[-2*w-1,-2*w-2,2*w-1]]); d, u, v = m.smith_form(); u * m * v == d 

True 

sage: m = matrix(OE, 3, 3, [-5*w-1,-2*w-2,4*w-10,8*w,-w,w-1,-1,1,-8]); d,u,v = m.smith_form(); u*m*v == d 

True 

""" 

R = self.base_ring() 

left_mat = self.new_matrix(self.nrows(), self.nrows(), 1) 

right_mat = self.new_matrix(self.ncols(), self.ncols(), 1) 

if self == 0 or (self.nrows() <= 1 and self.ncols() <= 1): 

return self.__copy__(), left_mat, right_mat 

  

# data type checks on R 

if not R.is_integral_domain() or not R.is_noetherian(): 

raise TypeError("Smith form only defined over Noetherian integral domains") 

if not R.is_exact(): 

raise NotImplementedError("Smith form over non-exact rings not implemented at present") 

  

# first clear the first row and column 

u,t,v = _smith_onestep(self) 

  

# now recurse: t now has a nonzero entry at 0,0 and zero entries in the rest 

# of the 0th row and column, so we apply smith_form to the smaller submatrix 

mm = t.submatrix(1,1) 

dd, uu, vv = mm.smith_form() 

mone = self.new_matrix(1, 1, [1]) 

d = dd.new_matrix(1,1,[t[0,0]]).block_sum(dd) 

u = uu.new_matrix(1,1,[1]).block_sum(uu) * u 

v = v * vv.new_matrix(1,1,[1]).block_sum(vv) 

dp, up, vp = _smith_diag(d) 

return dp,up*u,v*vp 

  

def _hermite_form_euclidean(self, transformation=False, normalization=None): 

""" 

Transform the matrix in place to hermite normal form and optionally 

return the transformation matrix. 

  

The matrix is assumed to be over an Euclidean domain. In particular, 

``xgcd()`` method should be available for the elements of the domain. 

  

INPUT: 

  

- ``transformation`` -- boolean (default: ``False``); if ``True``, 

return the transformation matrix 

  

- ``normalization`` -- function (default: ``None``); if given, the 

function is applied to each pivot to get a normalization coefficient, 

which is multiplied to the pivot. 

  

EXAMPLES:: 

  

sage: B = matrix(ZZ, 3, [-1,-2,-3,4,5,6,7,8,9]); B 

[-1 -2 -3] 

[ 4 5 6] 

[ 7 8 9] 

sage: C = B.__copy__() 

sage: U = C._hermite_form_euclidean(transformation=True) 

sage: C 

[1 2 3] 

[0 3 6] 

[0 0 0] 

sage: U 

[-1 0 0] 

[-4 -1 0] 

[-1 -2 1] 

sage: U * B == C 

True 

  

sage: P.<x> = PolynomialRing(QQ) 

sage: A = matrix(P,3,[-(x-1)^((i-j) % 3) for i in range(3) for j in range(3)]) 

sage: A 

[ -1 -x^2 + 2*x - 1 -x + 1] 

[ -x + 1 -1 -x^2 + 2*x - 1] 

[-x^2 + 2*x - 1 -x + 1 -1] 

sage: H = A.__copy__() 

sage: U = H._hermite_form_euclidean(transformation=True, normalization=lambda p: ~p.lc()) 

sage: H 

[ 1 x^2 - 2*x + 1 x - 1] 

[ 0 x^3 - 3*x^2 + 3*x - 2 0] 

[ 0 0 x^3 - 3*x^2 + 3*x - 2] 

sage: U * A == H 

True 

""" 

cdef Matrix A = self 

cdef Matrix U 

  

cdef Py_ssize_t m = A.nrows() 

cdef Py_ssize_t n = A.ncols() 

  

cdef Py_ssize_t i = 0 

cdef Py_ssize_t j = 0 

  

cdef Py_ssize_t k, l 

  

if transformation: 

from sage.matrix.constructor import identity_matrix 

U = identity_matrix(A.base_ring(), m) 

  

pivot_cols = [] 

while j < n: 

k = i 

while k < m and A.get_unsafe(k,j).is_zero(): # first nonzero entry 

k += 1 

if k < m: 

l = k + 1 

while l < m: 

while l < m and A.get_unsafe(l,j).is_zero(): # nonzero entry below 

l += 1 

if l >= m: break 

  

a = A.get_unsafe(k,j) 

b = A.get_unsafe(l,j) 

d,p,q = a.xgcd(b) # p * a + q * b = d = gcd(a,b) 

e = a // d 

f = b // d 

  

for c in range(j,n): 

Akc = A.get_unsafe(k,c) 

Alc = A.get_unsafe(l,c) 

A.set_unsafe(k, c, p * Akc + q * Alc) 

A.set_unsafe(l, c, (-f) * Akc + e * Alc) 

if transformation: 

for c in range(m): 

Ukc = U.get_unsafe(k,c) 

Ulc = U.get_unsafe(l,c) 

U.set_unsafe(k, c, p * Ukc + q * Ulc) 

U.set_unsafe(l, c, (-f) * Ukc + e * Ulc) 

if i != k: 

A.swap_rows(i,k) 

if transformation: 

U.swap_rows(i,k) 

pivot_cols.append(j) 

i += 1 

j += 1 

  

# reduce entries above pivots 

for i in range(len(pivot_cols)): 

j = pivot_cols[i] 

pivot = A.get_unsafe(i,j) 

  

# possibly normalize the pivot 

if normalization: 

coeff = normalization(pivot) 

for c in range(j,n): 

A.set_unsafe(i, c, A.get_unsafe(i,c) * coeff) 

if transformation: 

for c in range(m): 

U.set_unsafe(i, c, U.get_unsafe(i,c) * coeff) 

  

pivot = A.get_unsafe(i,j) 

for k in range(i): 

q = - (A.get_unsafe(k,j) // pivot) 

if not q.is_zero(): 

for c in range(j,n): 

A.set_unsafe(k, c, A.get_unsafe(k,c) + q * A.get_unsafe(i,c)) 

if transformation: 

for c in range(m): 

U.set_unsafe(k, c, U.get_unsafe(k,c) + q * U.get_unsafe(i,c)) 

  

if transformation: 

return U 

  

def hermite_form(self, include_zero_rows=True, transformation=False): 

""" 

Return the Hermite form of self, if it is defined. 

  

INPUT: 

  

- ``include_zero_rows`` -- bool (default: True); if False 

the zero rows in the output matrix are deleted. 

  

- ``transformation`` -- bool (default: False) a matrix U such that U*self == H. 

  

OUTPUT: 

  

- matrix H 

- (optional) transformation matrix U such that U*self == H, possibly with zero 

rows deleted... 

  

  

EXAMPLES:: 

  

sage: M = FunctionField(GF(7),'x').maximal_order() 

sage: K.<x> = FunctionField(GF(7)); M = K.maximal_order() 

sage: A = matrix(M, 2, 3, [x, 1, 2*x, x, 1+x, 2]) 

sage: A.hermite_form() 

[ x 1 2*x] 

[ 0 x 5*x + 2] 

sage: A.hermite_form(transformation=True) 

( 

[ x 1 2*x] [1 0] 

[ 0 x 5*x + 2], [6 1] 

) 

sage: A = matrix(M, 2, 3, [x, 1, 2*x, 2*x, 2, 4*x]) 

sage: A.hermite_form(transformation=True, include_zero_rows=False) 

([ x 1 2*x], [1 0]) 

sage: H, U = A.hermite_form(transformation=True, include_zero_rows=True); H, U 

( 

[ x 1 2*x] [1 0] 

[ 0 0 0], [5 1] 

) 

sage: U*A == H 

True 

sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False) 

sage: U*A 

[ x 1 2*x] 

sage: U*A == H 

True 

""" 

left, H, pivots = self._echelon_form_PID() 

if not include_zero_rows: 

i = H.nrows() - 1 

while H.row(i) == 0: 

i -= 1 

H = H[:i+1] 

if transformation: 

left = left[:i+1] 

if transformation: 

return H, left 

else: 

return H 

  

def _echelon_form_PID(self): 

r""" 

Return a triple (left, a, pivots) where left*self == a and a is row 

echelon form (which in this case we define to mean Hermite normal 

form). 

  

When ideals of the base ring have a "small_residue" method (as is the 

case for number field ideals), we use this to reduce entries above each 

column pivot. 

  

AUTHOR: 

  

- David Loeffler (2009-06-01) 

  

- Moritz Minzlaff (2011-03-17): corrected code for matrices of one row; 

this fixed :trac:`9053` 

  

EXAMPLES:: 

  

sage: L.<a> = NumberField(x^3 - 2) 

sage: OL = L.ring_of_integers() 

  

We check some degenerate cases:: 

  

sage: m = matrix(OL, 0, 0, []); r,s,p = m._echelon_form_PID(); 

sage: (r,s,p) 

([], [], []) 

sage: r * m == s and r.det() == 1 

True 

sage: m = matrix(OL, 0, 1, []); r,s,p = m._echelon_form_PID(); 

sage: (r,s,p) 

([], [], []) 

sage: r * m == s and r.det() == 1 

True 

sage: m = matrix(OL, 1, 0, []); r,s,p = m._echelon_form_PID(); 

sage: (r,s,p) 

([1], [], []) 

sage: r * m == s and r.det() == 1 

True 

  

A 2x2 matrix:: 

  

sage: m = matrix(OL, 2, 2, [1,0, a, 2]); 

sage: r,s,p = m._echelon_form_PID(); (r,s,p) 

( 

[ 1 0] [1 0] 

[-a 1], [0 2], [0, 1] 

) 

sage: r * m == s and r.det() == 1 

True 

  

A larger example:: 

  

sage: m = matrix(OL, 3, 5, [a^2 - 3*a - 1, a^2 - 3*a + 1, a^2 + 1, 

....: -a^2 + 2, -3*a^2 - a - 1, -6*a - 1, a^2 - 3*a - 1, 

....: 2*a^2 + a + 5, -2*a^2 + 5*a + 1, -a^2 + 13*a - 3, 

....: -2*a^2 + 4*a - 2, -2*a^2 + 1, 2*a, a^2 - 6, 3*a^2 - a ]) 

sage: r,s,p = m._echelon_form_PID() 

sage: s[2] 

(0, 0, -3*a^2 - 18*a + 34, -68*a^2 + 134*a - 53, -111*a^2 + 275*a - 90) 

sage: r * m == s and r.det() == 1 

True 

  

We verify that :trac:`9053` is resolved:: 

  

sage: R.<x> = GF(7)[] 

sage: A = R^3 

sage: L = A.span([x*A.0 + (x^3 + 1)*A.1, x*A.2]) 

sage: M = A.span([x*L.0]) 

sage: M.0 in L 

True 

  

""" 

if self.ncols() == 0: 

return self.new_matrix(self.nrows(), self.nrows(), 1), self, [] 

  

if self.nrows() == 0: 

return self.new_matrix(self.nrows(), self.nrows(), 1), self, [] 

  

if self.nrows() == 1: 

if self.is_zero(): 

return self.new_matrix(self.nrows(), self.nrows(), 1), self, [] 

else: 

return self.new_matrix(self.nrows(), self.nrows(), 1), self, [ 

self.nonzero_positions_in_row(0)[0] ] 

  

R = self.base_ring() 

  

# data type checks on R 

if not R.is_integral_domain(): 

raise TypeError("Generic echelon form only defined over " 

"integral domains") 

if not R.is_exact(): 

raise NotImplementedError("Echelon form over generic non-exact " 

"rings not implemented at present") 

  

left_mat, a = _generic_clear_column(self) 

assert left_mat * self == a 

  

if a[0,0] != 0: 

aa = a.submatrix(1, 1) 

s, t, pivs = aa._echelon_form_PID() 

left_mat = s.new_matrix(1,1,[1]).block_sum(s) * left_mat 

a = left_mat * self 

pivs = [0] + [x + 1 for x in pivs] 

  

else: 

aa = a.submatrix(0, 1) 

s, t, pivs = aa._echelon_form_PID() 

left_mat = s * left_mat 

a = left_mat * self 

pivs = [x+1 for x in pivs] 

  

  

try: 

for i in xrange(1, len(pivs)): 

y = a[i][pivs[i]] 

I = R.ideal(y) 

s = a[0][pivs[i]] 

t = I.small_residue(s) 

v = R( (s-t) / y) 

  

left_mat.add_multiple_of_row(0, i, -v) 

a.add_multiple_of_row(0, i, -v) 

assert left_mat * self == a 

except AttributeError: # on I.small_residue 

pass 

  

return left_mat, a, pivs 

  

def _zigzag_form(self, bint basis=True): 

r""" 

Helper method for computation of ZigZag form. 

  

INPUT: 

  

- ``self`` - a square matrix over an exact field. 

  

- ``basis`` - default; ``True`` - controls whether or not to 

compute a change-of-basis matrix (also called a transformation 

matrix). 

  

OUTPUT: 

  

See the documentation for the :meth:`zigzag_form` method for a 

description of ZigZag form and notes on the algorithm employed. 

  

When ``basis=True`` four items are returned. The first is a matrix 

whose columns form a basis so that a matrix representation of ``self`` 

relative to this basis will be the ZigZag form. More precisely, if 

`A` is the matrix, `U` is the change-of-basis matrix and `Z` is 

the ZigZag form, then 

  

.. MATH:: 

  

U^{-1}*A*U = Z 

  

The second item returned is the ZigZag form of the matrix. The 

third item is a list of lists, where each list is the coefficients 

of the polynomial associated with a companion matrix in the form. 

Finally, the fourth item is a list of the entries in the upper-left 

corner of each off-diagonal block, which will be a zero or a one. 

The length of the list of corner entries will be one less than the 

length of list of polynomials. 

  

When ``basis=False`` only three items are returned. These are 

just as above, but without the change-of-basis matrix. 

  

The computation of the change-of-basis matrix has not been optimized. 

As a helper method, no error checking is performed on the inputs - 

that should be performed by the calling method. 

  

ALGORITHM: 

  

ZigZag form, and its computation, are due to Arne Storjohann 

and are described in [Sto2000]_ and 

[Sto1998]_, where the former is more 

representative of the code here. 

  

EXAMPLES: 

  

sage: A = matrix(QQ, [[-68, 69, -27, -11, -65, 9, -181, -32], 

....: [-52, 52, -27, -8, -52, -16, -133, -14], 

....: [ 92, -97, 47, 14, 90, 32, 241, 18], 

....: [139, -144, 60, 18, 148, -10, 362, 77], 

....: [ 40, -41, 12, 6, 45, -24, 105, 42], 

....: [-46, 48, -20, -7, -47, 0, -122, -22], 

....: [-26, 27, -13, -4, -29, -6, -66, -14], 

....: [-33, 34, -13, -5, -35, 7, -87, -23]]) 

sage: Z, polys, corners = A._zigzag_form(basis=False) 

sage: Z 

[ 0 0 0 40 1 0 0 0] 

[ 1 0 0 52 0 0 0 0] 

[ 0 1 0 18 0 0 0 0] 

[ 0 0 1 -1 0 0 0 0] 

[ 0 0 0 0 0 1 0 0] 

[ 0 0 0 0 -25 10 0 0] 

[ 0 0 0 0 1 0 0 -4] 

[ 0 0 0 0 0 0 1 -4] 

sage: polys 

[[-40, -52, -18, 1, 1], [25, -10, 1], [4, 4, 1]] 

sage: corners 

[1, 1] 

sage: len(polys) == len(corners) + 1 

True 

  

sage: U, X, polys, corners = A._zigzag_form() 

sage: 38416*U 

[ 38416 -2612288 -8797264 -47943168 83753660284 -16775074316 1574993574 -12141218334] 

[ 0 -1997632 -7222208 -38108672 66323477868 -13362573684 3694412232 -12414630592] 

[ 0 3534272 12523616 66920672 -116699384082 23442252424 -4176610942 18012693216] 

[ 0 5339824 18631760 100842000 -175585304193 35191011843 -3619613634 22708786576] 

[ 0 1536640 5301408 28812000 -50432310506 10071675864 79884994 5258177064] 

[ 0 -1767136 -6261808 -33460336 58377759731 -11719115889 1849749314 -8725304756] 

[ 0 -998816 -3611104 -19054336 33189768208 -6681286842 1651135654 -5815174372] 

[ 0 -1267728 -4456256 -23933168 41831027339 -8380482791 785625330 -5536675718] 

sage: X == Z 

True 

sage: U.inverse()*A*U == X 

True 

  

AUTHOR: 

  

- Rob Beezer (2011-06-09) 

""" 

cdef Py_ssize_t n, s, c, i, j, k 

  

n = self._ncols 

R = self.base_ring() 

zero = R.zero() 

one = R.one() 

cdef Matrix Z = self.__copy__() 

cdef list polys = [] # coefficients for polynomials of companion matrices 

cdef list corners = [] # zero or one in corner of off-diagonal blocks 

if basis: 

from sage.matrix.constructor import identity_matrix 

U = identity_matrix(R, n) # transformation matrix 

# parity switch, True iff working on transpose 

# if False, mimic row operations only on U 

# if True, mimic column operations only on U 

cdef bint trans = False, zigging 

s = 0 # index of top row of current block 

c = 0 # index of current row of current block 

while s < n: 

zigging = True 

# check for totally zero column below diagonal 

while zigging: # zigging means we are building a block 

nonzero = -1 

for i in range(c+1, n): 

if Z.get_unsafe(i,c): 

nonzero = i 

break 

zigging = (nonzero != -1) 

if zigging: 

Z.swap_rows(nonzero, c+1) 

Z.swap_columns(nonzero, c+1) 

if basis: 

if trans: 

U.swap_columns(nonzero, c+1) 

else: 

U.swap_rows(nonzero, c+1) 

  

# create a subdiagonal entry 1 

scale = Z.get_unsafe(c+1, c) 

Z.rescale_row(c+1, 1/scale) 

Z.rescale_col(c+1, scale) 

if basis: 

if trans: 

U.rescale_col(c+1, scale) 

else: 

U.rescale_row(c+1, ~scale) 

  

# clear column throughout the block,and in all rows below 

for i in range(s, n): 

if i != c+1: 

scale = Z.get_unsafe(i, c) 

Z.add_multiple_of_row(i, c+1, -scale) 

Z.add_multiple_of_column(c+1, i, scale) 

if basis: 

if trans: 

U.add_multiple_of_column(c+1, i, scale) 

else: 

U.add_multiple_of_row(i, c+1, -scale) 

# move to next column 

# column of coefficients will cause zero search to fail 

# at the top of this loop, and then we leave the column alone 

# having built a block 

c = c + 1 

  

# now have a companion matrix between rows s and c 

# (inclusive), use it to clear entries to the right 

# but first record polynomial for block just built 

# this is the full monic polynomial, with correct coefficients 

p = [-Z.get_unsafe(i,c) for i in range(s,c+1)] 

p.append(one) 

polys.append(p) 

  

# use new unit columns (i) to clear rows to right (j) 

# all but top row of block to the right will become zero 

# it is important that the loop on i goes in reverse 

for i in range(c-1, s-1, -1): 

for j in range(c+1, n): 

scale = Z.get_unsafe(i+1, j) 

# Effectively: Z.add_multiple_of_column(j, i, -scale) 

Z.set_unsafe(i+1, j, zero) 

# row j leads with zeros, up to, and including column c 

# Effectively: Z.add_multiple_of_row(i, j, scale) 

for k in range(c+1, n): 

# Z[i,k] = Z[i,k] + scale*Z[j,k] 

Z.set_unsafe(i, k, Z.get_unsafe(i,k)+scale*Z.get_unsafe(j,k)) 

if basis: 

if trans: 

U.add_multiple_of_column(j, i, -scale) 

else: 

U.add_multiple_of_row(i, j, scale) 

  

# row s to the right of the block needs care 

# we will be left with a leading one, or totally zeros 

nonzero = -1 

# locate a nonzero entry in row s 

for j in range(c+1, n): 

if Z.get_unsafe(s, j): 

nonzero = j 

break 

if (nonzero != -1): 

# swap column wih nonzero entry just outside block 

if nonzero != c+1: 

Z.swap_columns(c+1, nonzero) 

Z.swap_rows(c+1, nonzero) 

if basis: 

if trans: 

U.swap_columns(c+1, nonzero) 

else: 

U.swap_rows(c+1, nonzero) 

scale = Z.get_unsafe(s, c+1) 

Z.rescale_col(c+1, ~scale) 

Z.rescale_row(c+1, scale) 

if basis: 

if trans: 

U.rescale_col(c+1, ~scale) 

else: 

U.rescale_row(c+1, scale) 

for j in range(c+2, n): 

scale = Z.get_unsafe(s, j) 

# exploiting leading zeros does not seem too beneficial here 

Z.add_multiple_of_column(j, c+1, -scale) 

Z.add_multiple_of_row(c+1, j, scale) 

if basis: 

if trans: 

U.add_multiple_of_column(j, c+1, -scale) 

else: 

U.add_multiple_of_row(c+1, j, scale) 

  

# maybe move this closer to where we know which it is 

if c < n-1: 

corners.append(Z.get_unsafe(s, c+1)) 

# reset indices for constructing next block 

# transpose all elements, this is a zig or a zag 

c = c+1 

s = c 

Z = Z.transpose() 

if basis: 

U = U.transpose() 

trans = not trans 

  

# maybe return to un-transposed state 

if trans: 

Z = Z.transpose() 

if basis: 

U = U.transpose() 

if basis: 

# Storjohann computes U, we return its inverse 

# after this step, the columns of U are basis for representing self 

# code could be re-arranged to compute U's inverse directly 

return U.inverse(), Z, polys, corners 

return Z, polys, corners 

  

def zigzag_form(self, subdivide=True, transformation=False): 

r""" 

Find a matrix in ZigZag form that is similar to ``self``. 

  

INPUT: 

  

- ``self`` - a square matrix with entries from an exact field. 

  

- ``transformation`` - default: False - if ``True`` return a 

change-of-basis matrix relating the matrix and its ZigZag form. 

  

- ``subdivide`` - default: ``True`` - if ``True`` the ZigZag 

form matrix is subdivided according to the companion matrices 

described in the output section below. 

  

OUTPUT: 

  

A matrix in ZigZag form has blocks on the main diagonal that are 

companion matrices. The first companion matrix has ones just below 

the main diagonal. The last column has the negatives of coefficients 

of a monic polynomial, but not the leading one. Low degree monomials 

have their coefficients in the earlier rows. The second companion 

matrix is like the first only transposed. The third is like the first. 

The fourth is like the second. And so on. 

  

These blocks on the main diagonal define blocks just off the diagonal. 

To the right of the first companion matrix, and above the second 

companion matrix is a block that is totally zero, except the entry 

of the first row and first column may be a one. Below the second 

block and to the left of the third block is a block that is totally 

zero, except the entry of the first row and first column may be one. 

This alternating pattern continues. It may now be apparent how this 

form gets its name. Any other entry of the matrix is zero. So this 

form is reminiscent of rational canonical form and is a good precursor 

to that form. 

  

If ``transformation`` is ``True``, then the output is a pair of 

matrices. The first is the form ``Z`` and the second is an invertible 

matrix ``U`` such that ``U.inverse()*self*U`` equals ``Z``. In other 

words, the representation of ``self`` with respect to the columns 

of ``U`` will be ``Z``. 

  

If subdivide is ``True`` then the matrix returned as the form is 

partitioned according to the companion matrices and these may be 

manipulated by several different matrix methods. 

  

For output that may be more useful as input to other routines, 

see the helper method :meth:`_zigzag_form`. 

  

.. NOTE:: 

  

An effort has been made to optimize computation of the form, 

but no such work has been done for the computation of the 

transformation matrix, so for fastest results do not request the 

transformation matrix. 

  

ALGORITHM: 

  

ZigZag form, and its computation, are due to Arne Storjohann 

and are described in [Sto2000]_ and 

[Sto1998]_, where the former is more 

representative of the code here. 

  

EXAMPLES: 

  

Two examples that illustrate ZigZag form well. Notice that this is 

*not* a canonical form. The two matrices below are similar, since 

they have equal Jordan canonical forms, yet their ZigZag forms are 

quite different. In other words, while the computation of the form 

is deterministic, the final result, when viewed as a property of a 

linear transformation, is dependent on the basis used for the 

matrix representation. :: 

  

sage: A = matrix(QQ, [[-68, 69, -27, -11, -65, 9, -181, -32], 

....: [-52, 52, -27, -8, -52, -16, -133, -14], 

....: [ 92, -97, 47, 14, 90, 32, 241, 18], 

....: [139, -144, 60, 18, 148, -10, 362, 77], 

....: [ 40, -41, 12, 6, 45, -24, 105, 42], 

....: [-46, 48, -20, -7, -47, 0, -122, -22], 

....: [-26, 27, -13, -4, -29, -6, -66, -14], 

....: [-33, 34, -13, -5, -35, 7, -87, -23]]) 

sage: Z, U = A.zigzag_form(transformation=True) 

sage: Z 

[ 0 0 0 40| 1 0| 0 0] 

[ 1 0 0 52| 0 0| 0 0] 

[ 0 1 0 18| 0 0| 0 0] 

[ 0 0 1 -1| 0 0| 0 0] 

[---------------+-------+-------] 

[ 0 0 0 0| 0 1| 0 0] 

[ 0 0 0 0|-25 10| 0 0] 

[---------------+-------+-------] 

[ 0 0 0 0| 1 0| 0 -4] 

[ 0 0 0 0| 0 0| 1 -4] 

sage: U.inverse()*A*U == Z 

True 

  

sage: B = matrix(QQ, [[ 16, 69, -13, 2, -52, 143, 90, -3], 

....: [ 26, 54, 6, -5, -28, 73, 73, -48], 

....: [-16, -79, 12, -10, 64, -142, -115, 41], 

....: [ 27, -7, 21, -33, 39, -20, -42, 43], 

....: [ 8, -75, 34, -32, 86, -156, -130, 42], 

....: [ 2, -17, 7, -8, 20, -33, -31, 16], 

....: [-24, -80, 7, -3, 56, -136, -112, 42], 

....: [ -6, -19, 0, -1, 13, -28, -27, 15]]) 

sage: Z, U = B.zigzag_form(transformation=True) 

sage: Z 

[ 0 0 0 0 0 1000| 0| 0] 

[ 1 0 0 0 0 900| 0| 0] 

[ 0 1 0 0 0 -30| 0| 0] 

[ 0 0 1 0 0 -153| 0| 0] 

[ 0 0 0 1 0 3| 0| 0] 

[ 0 0 0 0 1 9| 0| 0] 

[-----------------------------+----+----] 

[ 0 0 0 0 0 0| -2| 0] 

[-----------------------------+----+----] 

[ 0 0 0 0 0 0| 1| -2] 

sage: U.inverse()*B*U == Z 

True 

  

sage: A.jordan_form() == B.jordan_form() 

True 

  

Two more examples, illustrating the two extremes of the zig-zag 

nature of this form. The first has a one in each of the 

off-diagonal blocks, the second has all zeros in each off-diagonal 

block. Notice again that the two matrices are similar, since their 

Jordan canonical forms are equal. :: 

  

sage: C = matrix(QQ, [[2, 31, -10, -9, -125, 13, 62, -12], 

....: [0, 48, -16, -16, -188, 20, 92, -16], 

....: [0, 9, -1, 2, -33, 5, 18, 0], 

....: [0, 15, -5, 0, -59, 7, 30, -4], 

....: [0, -21, 7, 2, 84, -10, -42, 5], 

....: [0, -42, 14, 8, 167, -17, -84, 13], 

....: [0, -50, 17, 10, 199, -23, -98, 14], 

....: [0, 15, -5, -2, -59, 7, 30, -2]]) 

sage: Z, U = C.zigzag_form(transformation=True) 

sage: Z 

[2|1|0|0|0|0|0|0] 

[-+-+-+-+-+-+-+-] 

[0|2|0|0|0|0|0|0] 

[-+-+-+-+-+-+-+-] 

[0|1|2|1|0|0|0|0] 

[-+-+-+-+-+-+-+-] 

[0|0|0|2|0|0|0|0] 

[-+-+-+-+-+-+-+-] 

[0|0|0|1|2|1|0|0] 

[-+-+-+-+-+-+-+-] 

[0|0|0|0|0|2|0|0] 

[-+-+-+-+-+-+-+-] 

[0|0|0|0|0|1|2|1] 

[-+-+-+-+-+-+-+-] 

[0|0|0|0|0|0|0|2] 

sage: U.inverse()*C*U == Z 

True 

  

sage: D = matrix(QQ, [[ -4, 3, 7, 2, -4, 5, 7, -3], 

....: [ -6, 5, 7, 2, -4, 5, 7, -3], 

....: [ 21, -12, 89, 25, 8, 27, 98, -95], 

....: [ -9, 5, -44, -11, -3, -13, -48, 47], 

....: [ 23, -13, 74, 21, 12, 22, 85, -84], 

....: [ 31, -18, 135, 38, 12, 47, 155, -147], 

....: [-33, 19, -138, -39, -13, -45, -156, 151], 

....: [ -7, 4, -29, -8, -3, -10, -34, 34]]) 

sage: Z, U = D.zigzag_form(transformation=True) 

sage: Z 

[ 0 -4| 0 0| 0 0| 0 0] 

[ 1 4| 0 0| 0 0| 0 0] 

[-----+-----+-----+-----] 

[ 0 0| 0 1| 0 0| 0 0] 

[ 0 0|-4 4| 0 0| 0 0] 

[-----+-----+-----+-----] 

[ 0 0| 0 0| 0 -4| 0 0] 

[ 0 0| 0 0| 1 4| 0 0] 

[-----+-----+-----+-----] 

[ 0 0| 0 0| 0 0| 0 1] 

[ 0 0| 0 0| 0 0|-4 4] 

sage: U.inverse()*D*U == Z 

True 

  

sage: C.jordan_form() == D.jordan_form() 

True 

  

ZigZag form is achieved entirely with the operations of the field, so 

while the eigenvalues may lie outside the field, this does not impede 

the computation of the form. :: 

  

sage: F.<a> = GF(5^4) 

sage: A = matrix(F, [[ a, 0, 0, a + 3], 

....: [ 0,a^2 + 1, 0, 0], 

....: [ 0, 0,a^3, 0], 

....: [a^2 +4 , 0, 0,a + 2]]) 

sage: A.zigzag_form() 

[ 0 a^3 + 2*a^2 + 2*a + 2| 0| 0] 

[ 1 2*a + 2| 0| 0] 

[-------------------------------------------+---------------------+---------------------] 

[ 0 0| a^3| 0] 

[-------------------------------------------+---------------------+---------------------] 

[ 0 0| 0| a^2 + 1] 

sage: A.eigenvalues() 

Traceback (most recent call last): 

... 

NotImplementedError: algebraic closures of finite fields are only implemented for prime fields 

  

Subdivisions are optional. :: 

  

sage: F.<a> = GF(5^4) 

sage: A = matrix(F, [[ a, 0, 0, a + 3], 

....: [ 0,a^2 + 1, 0, 0], 

....: [ 0, 0,a^3, 0], 

....: [a^2 +4 , 0, 0,a + 2]]) 

sage: A.zigzag_form(subdivide=False) 

[ 0 a^3 + 2*a^2 + 2*a + 2 0 0] 

[ 1 2*a + 2 0 0] 

[ 0 0 a^3 0] 

[ 0 0 0 a^2 + 1] 

  

TESTS:: 

  

sage: A = matrix(QQ, 2, 3, range(6)) 

sage: A.zigzag_form() 

Traceback (most recent call last): 

... 

TypeError: matrix must be square, not 2 x 3 

  

sage: A = matrix(Integers(6), 2, 2, range(4)) 

sage: A.zigzag_form() 

Traceback (most recent call last): 

... 

TypeError: matrix entries must come from an exact field, not Ring of integers modulo 6 

  

sage: A = matrix(RDF, 2, 2, range(4)) 

sage: A.zigzag_form() 

Traceback (most recent call last): 

... 

TypeError: matrix entries must come from an exact field, not Real Double Field 

  

sage: A = matrix(QQ, 2, range(4)) 

sage: A.zigzag_form(transformation='junk') 

Traceback (most recent call last): 

... 

ValueError: 'transformation' keyword must be True or False, not junk 

  

sage: A = matrix(QQ, 2, range(4)) 

sage: A.zigzag_form(subdivide='garbage') 

Traceback (most recent call last): 

... 

ValueError: 'subdivide' keyword must be True or False, not garbage 

  

AUTHOR: 

  

- Rob Beezer (2011-06-09) 

""" 

R = self.base_ring() 

if not self.is_square(): 

raise TypeError("matrix must be square, not {0} x {1}".format(self.nrows(), self.ncols())) 

if not (R.is_field() and R.is_exact()): 

raise TypeError("matrix entries must come from an exact field, not {0}".format(R)) 

if transformation not in [True, False]: 

raise ValueError("'transformation' keyword must be True or False, not {0}".format(transformation)) 

if subdivide not in [True, False]: 

raise ValueError("'subdivide' keyword must be True or False, not {0}".format(subdivide)) 

if transformation: 

U, Z, polys, corners = self._zigzag_form(basis=True) 

else: 

Z, polys, corners = self._zigzag_form(basis=False) 

if subdivide: 

s = 0 

splits = [] 

for p in polys[:-1]: 

s = s + len(p) - 1 

splits.append(s) 

Z.subdivide(splits, splits) 

if transformation: 

return Z, U 

else: 

return Z 

  

def rational_form(self, format='right', subdivide=True): 

r""" 

Returns the rational canonical form, also known as Frobenius form. 

  

INPUT: 

  

- ``self`` - a square matrix with entries from an exact field. 

  

- ``format`` - default: 'right' - one of 'right', 'bottom', 

'left', 'top' or 'invariants'. The first four will cause a 

matrix to be returned with companion matrices dictated by the 

keyword. The value 'invariants' will cause a list of lists to 

be returned, where each list contains coefficients of a 

polynomial associated with a companion matrix. 

  

- ``subdivide`` - default: 'True' - if 'True' and a matrix is 

returned, then it contains subdivisions delineating the 

companion matrices along the diagonal. 

  

OUTPUT: 

  

The rational form of a matrix is a similar matrix composed of 

submatrices ("blocks") placed on the main diagonal. Each block 

is a companion matrix. Associated with each companion matrix is a 

polynomial. In rational form, the polynomial of one block will 

divide the polynomial of the next block (and thus, the polynomials 

of all subsequent blocks). 

  

Rational form, also known as Frobenius form, is a canonical form. 

In other words, two matrices are similar if and only if their 

rational canonical forms are equal. The algorithm used does not 

provide the similarity transformation matrix (also known as the 

change-of-basis matrix). 

  

Companion matrices may be written in one of four styles, and any 

such style may be selected with the ``format`` keyword. See the 

companion matrix constructor, 

:meth:`sage.matrix.constructor.companion_matrix`, 

for more information about companion matrices. 

  

If the 'invariants' value is used for the ``format`` keyword, 

then the return value is a list of lists, where each list is the 

coefficients of the polynomial associated with one of the companion 

matrices on the diagonal. These coefficients include the leading 

one of the monic polynomial and are ready to be coerced into 

any polynomial ring over the same field (see examples of this below). 

This return value is intended to be the most compact representation 

and the easiest to use for testing equality of rational forms. 

  

Because the minimal and characteristic polynomials of a companion 

matrix are the associated polynomial, it is easy to see that the 

product of the polynomials of the blocks will be the characteristic 

polynomial and the final polynomial will be the minimal polynomial 

of the entire matrix. 

  

ALGORITHM: 

  

We begin with ZigZag form, which is due to Arne Storjohann 

and is documented at :meth:`zigzag_form`. Then we eliminate 

''corner'' entries enroute to rational form via an additional 

algorithm of Storjohann's [Sto2011]_. 

  

EXAMPLES: 

  

The lists of coefficients returned with the ``invariants`` keyword 

are designed to easily convert to the polynomials associated with 

the companion matrices. This is illustrated by the construction 

below of the ``polys`` list. Then we can test the divisibility 

condition on the list of polynomials. Also the minimal and 

characteristic polynomials are easy to determine from this list. :: 

  

sage: A = matrix(QQ, [[ 11, 14, -15, -4, -38, -29, 1, 23, 14, -63, 17, 24, 36, 32], 

....: [ 18, 6, -17, -11, -31, -43, 12, 26, 0, -69, 11, 13, 17, 24], 

....: [ 11, 16, -22, -8, -48, -34, 0, 31, 16, -82, 26, 31, 39, 37], 

....: [ -8, -18, 22, 10, 46, 33, 3, -27, -12, 70, -19, -20, -42, -31], 

....: [-13, -21, 16, 10, 52, 43, 4, -28, -25, 89, -37, -20, -53, -62], 

....: [ -2, -6, 0, 0, 6, 10, 1, 1, -7, 14, -11, -3, -10, -18], 

....: [ -9, -19, -3, 4, 23, 30, 8, -3, -27, 55, -40, -5, -40, -69], 

....: [ 4, -8, -1, -1, 5, -4, 9, 5, -11, 4, -14, -2, -13, -17], 

....: [ 1, -2, 16, -1, 19, -2, -1, -17, 2, 19, 5, -25, -7, 14], 

....: [ 7, 7, -13, -4, -26, -21, 3, 18, 5, -40, 7, 15, 20, 14], 

....: [ -6, -7, -12, 4, -1, 18, 3, 8, -11, 15, -18, 17, -15, -41], 

....: [ 5, 11, -11, -3, -26, -19, -1, 14, 10, -42, 14, 17, 25, 23], 

....: [-16, -15, 3, 10, 29, 45, -1, -13, -19, 71, -35, -2, -35, -65], 

....: [ 4, 2, 3, -2, -2, -10, 1, 0, 3, -11, 6, -4, 6, 17]]) 

sage: A.rational_form() 

[ 0 -4| 0 0 0 0| 0 0 0 0 0 0 0 0] 

[ 1 4| 0 0 0 0| 0 0 0 0 0 0 0 0] 

[---------+-------------------+---------------------------------------] 

[ 0 0| 0 0 0 12| 0 0 0 0 0 0 0 0] 

[ 0 0| 1 0 0 -4| 0 0 0 0 0 0 0 0] 

[ 0 0| 0 1 0 -9| 0 0 0 0 0 0 0 0] 

[ 0 0| 0 0 1 6| 0 0 0 0 0 0 0 0] 

[---------+-------------------+---------------------------------------] 

[ 0 0| 0 0 0 0| 0 0 0 0 0 0 0 -216] 

[ 0 0| 0 0 0 0| 1 0 0 0 0 0 0 108] 

[ 0 0| 0 0 0 0| 0 1 0 0 0 0 0 306] 

[ 0 0| 0 0 0 0| 0 0 1 0 0 0 0 -271] 

[ 0 0| 0 0 0 0| 0 0 0 1 0 0 0 -41] 

[ 0 0| 0 0 0 0| 0 0 0 0 1 0 0 134] 

[ 0 0| 0 0 0 0| 0 0 0 0 0 1 0 -64] 

[ 0 0| 0 0 0 0| 0 0 0 0 0 0 1 13] 

  

sage: R = PolynomialRing(QQ, 'x') 

sage: invariants = A.rational_form(format='invariants') 

sage: invariants 

[[4, -4, 1], [-12, 4, 9, -6, 1], [216, -108, -306, 271, 41, -134, 64, -13, 1]] 

sage: polys = [R(p) for p in invariants] 

sage: [p.factor() for p in polys] 

[(x - 2)^2, (x - 3) * (x + 1) * (x - 2)^2, (x + 1)^2 * (x - 3)^3 * (x - 2)^3] 

sage: all(polys[i].divides(polys[i+1]) for i in range(len(polys)-1)) 

True 

sage: polys[-1] == A.minimal_polynomial(var='x') 

True 

sage: prod(polys) == A.characteristic_polynomial(var='x') 

True 

  

Rational form is a canonical form. Any two matrices are similar 

if and only if their rational forms are equal. By starting with 

Jordan canonical forms, the matrices ``C`` and ``D`` below were 

built as similar matrices, while ``E`` was built to be just 

slightly different. All three matrices have equal characteristic 

polynomials though ``E``'s minimal polynomial differs. :: 

  

sage: C = matrix(QQ, [[2, 31, -10, -9, -125, 13, 62, -12], 

....: [0, 48, -16, -16, -188, 20, 92, -16], 

....: [0, 9, -1, 2, -33, 5, 18, 0], 

....: [0, 15, -5, 0, -59, 7, 30, -4], 

....: [0, -21, 7, 2, 84, -10, -42, 5], 

....: [0, -42, 14, 8, 167, -17, -84, 13], 

....: [0, -50, 17, 10, 199, -23, -98, 14], 

....: [0, 15, -5, -2, -59, 7, 30, -2]]) 

sage: C.minimal_polynomial().factor() 

(x - 2)^2 

sage: C.characteristic_polynomial().factor() 

(x - 2)^8 

sage: C.rational_form() 

[ 0 -4| 0 0| 0 0| 0 0] 

[ 1 4| 0 0| 0 0| 0 0] 

[-----+-----+-----+-----] 

[ 0 0| 0 -4| 0 0| 0 0] 

[ 0 0| 1 4| 0 0| 0 0] 

[-----+-----+-----+-----] 

[ 0 0| 0 0| 0 -4| 0 0] 

[ 0 0| 0 0| 1 4| 0 0] 

[-----+-----+-----+-----] 

[ 0 0| 0 0| 0 0| 0 -4] 

[ 0 0| 0 0| 0 0| 1 4] 

  

sage: D = matrix(QQ, [[ -4, 3, 7, 2, -4, 5, 7, -3], 

....: [ -6, 5, 7, 2, -4, 5, 7, -3], 

....: [ 21, -12, 89, 25, 8, 27, 98, -95], 

....: [ -9, 5, -44, -11, -3, -13, -48, 47], 

....: [ 23, -13, 74, 21, 12, 22, 85, -84], 

....: [ 31, -18, 135, 38, 12, 47, 155, -147], 

....: [-33, 19, -138, -39, -13, -45, -156, 151], 

....: [ -7, 4, -29, -8, -3, -10, -34, 34]]) 

sage: D.minimal_polynomial().factor() 

(x - 2)^2 

sage: D.characteristic_polynomial().factor() 

(x - 2)^8 

sage: D.rational_form() 

[ 0 -4| 0 0| 0 0| 0 0] 

[ 1 4| 0 0| 0 0| 0 0] 

[-----+-----+-----+-----] 

[ 0 0| 0 -4| 0 0| 0 0] 

[ 0 0| 1 4| 0 0| 0 0] 

[-----+-----+-----+-----] 

[ 0 0| 0 0| 0 -4| 0 0] 

[ 0 0| 0 0| 1 4| 0 0] 

[-----+-----+-----+-----] 

[ 0 0| 0 0| 0 0| 0 -4] 

[ 0 0| 0 0| 0 0| 1 4] 

  

sage: E = matrix(QQ, [[ 0, -8, 4, -6, -2, 5, -3, 11], 

....: [-2, -4, 2, -4, -2, 4, -2, 6], 

....: [ 5, 14, -7, 12, 3, -8, 6, -27], 

....: [-3, -8, 7, -5, 0, 2, -6, 17], 

....: [ 0, 5, 0, 2, 4, -4, 1, 2], 

....: [-3, -7, 5, -6, -1, 5, -4, 14], 

....: [ 6, 18, -10, 14, 4, -10, 10, -28], 

....: [-2, -6, 4, -5, -1, 3, -3, 13]]) 

sage: E.minimal_polynomial().factor() 

(x - 2)^3 

sage: E.characteristic_polynomial().factor() 

(x - 2)^8 

sage: E.rational_form() 

[ 2| 0 0| 0 0| 0 0 0] 

[---+-------+-------+-----------] 

[ 0| 0 -4| 0 0| 0 0 0] 

[ 0| 1 4| 0 0| 0 0 0] 

[---+-------+-------+-----------] 

[ 0| 0 0| 0 -4| 0 0 0] 

[ 0| 0 0| 1 4| 0 0 0] 

[---+-------+-------+-----------] 

[ 0| 0 0| 0 0| 0 0 8] 

[ 0| 0 0| 0 0| 1 0 -12] 

[ 0| 0 0| 0 0| 0 1 6] 

  

  

The principal feature of rational canonical form is that it 

can be computed over any field using only field operations. Other 

forms, such as Jordan canonical form, are complicated by the need to 

determine the eigenvalues of the matrix, which can lie outside 

the field. The following matrix has all of its eigenvalues 

outside the rationals - some are irrational (`\pm\sqrt{2}`) and 

the rest are complex (`-1\pm 2i`). :: 

  

sage: A = matrix(QQ, 

....: [[-154, -3, -54, 44, 48, -244, -19, 67, -326, 85, 355, 581], 

....: [ 504, 25, 156, -145, -171, 793, 99, -213, 1036, -247, -1152, -1865], 

....: [ 294, -1, 112, -89, -90, 469, 36, -128, 634, -160, -695, -1126], 

....: [ -49, -32, 25, 7, 37, -64, -58, 12, -42, -14, 72, 106], 

....: [-261, -123, 65, 47, 169, -358, -254, 70, -309, -29, 454, 673], 

....: [-448, -123, -10, 109, 227, -668, -262, 163, -721, 95, 896, 1410], 

....: [ 38, 7, 8, -14, -17, 66, 6, -23, 73, -29, -78, -143], 

....: [ -96, 10, -55, 37, 24, -168, 17, 56, -231, 88, 237, 412], 

....: [ 310, 67, 31, -81, -143, 473, 143, -122, 538, -98, -641, -1029], 

....: [ 139, -35, 99, -49, -18, 236, -41, -70, 370, -118, -377, -619], 

....: [ 243, 9, 81, -72, -81, 386, 43, -105, 508, -124, -564, -911], 

....: [-155, -3, -55, 45, 50, -245, -27, 65, -328, 77, 365, 583]]) 

sage: A.characteristic_polynomial().factor() 

(x^2 - 2)^2 * (x^2 + 2*x + 5)^4 

sage: A.eigenvalues(extend=False) 

[] 

sage: A.rational_form() 

[ 0 -5| 0 0 0 0| 0 0 0 0 0 0] 

[ 1 -2| 0 0 0 0| 0 0 0 0 0 0] 

[-------+---------------+-----------------------] 

[ 0 0| 0 0 0 10| 0 0 0 0 0 0] 

[ 0 0| 1 0 0 4| 0 0 0 0 0 0] 

[ 0 0| 0 1 0 -3| 0 0 0 0 0 0] 

[ 0 0| 0 0 1 -2| 0 0 0 0 0 0] 

[-------+---------------+-----------------------] 

[ 0 0| 0 0 0 0| 0 0 0 0 0 50] 

[ 0 0| 0 0 0 0| 1 0 0 0 0 40] 

[ 0 0| 0 0 0 0| 0 1 0 0 0 3] 

[ 0 0| 0 0 0 0| 0 0 1 0 0 -12] 

[ 0 0| 0 0 0 0| 0 0 0 1 0 -12] 

[ 0 0| 0 0 0 0| 0 0 0 0 1 -4] 

sage: F.<x> = QQ[] 

sage: polys = A.rational_form(format='invariants') 

sage: [F(p).factor() for p in polys] 

[x^2 + 2*x + 5, (x^2 - 2) * (x^2 + 2*x + 5), (x^2 - 2) * (x^2 + 2*x + 5)^2] 

  

Rational form may be computed over any field. The matrix below is 

an example where the eigenvalues lie outside the field. :: 

  

sage: F.<a> = FiniteField(7^2) 

sage: A = matrix(F, 

....: [[5*a + 3, 4*a + 1, 6*a + 2, 2*a + 5, 6, 4*a + 5, 4*a + 5, 5, a + 6, 5, 4*a + 4], 

....: [6*a + 3, 2*a + 4, 0, 6, 5*a + 5, 2*a, 5*a + 1, 1, 5*a + 2, 4*a, 5*a + 6], 

....: [3*a + 1, 6*a + 6, a + 6, 2, 0, 3*a + 6, 5*a + 4, 5*a + 6, 5*a + 2, 3, 4*a + 2], 

....: [ 3*a, 6*a, 3*a, 4*a, 4*a + 4, 3*a + 6, 6*a, 4, 3*a + 4, 6*a + 2, 4*a], 

....: [4*a + 5, a + 1, 4*a + 3, 6*a + 5, 5*a + 2, 5*a + 2, 6*a, 4*a + 6, 6*a + 4, 5*a + 3, 3*a + 1], 

....: [ 3*a, 6*a, 4*a + 1, 6*a + 2, 2*a + 5, 4*a + 6, 2, a + 5, 2*a + 4, 2*a + 1, 2*a + 1], 

....: [4*a + 5, 3*a + 3, 6, 4*a + 1, 4*a + 3, 6*a + 3, 6, 3*a + 3, 3, a + 3, 0], 

....: [6*a + 6, a + 4, 2*a + 6, 3*a + 5, 4*a + 3, 2, a, 3*a + 4, 5*a, 2*a + 5, 4*a + 3], 

....: [3*a + 5, 6*a + 2, 4*a, a + 5, 0, 5*a, 6*a + 5, 2*a + 1, 3*a + 1, 3*a + 5, 4*a + 2], 

....: [3*a + 2, a + 3, 3*a + 6, a, 3*a + 5, 5*a + 1, 3*a + 2, a + 3, a + 2, 6*a + 1, 3*a + 3], 

....: [6*a + 6, 5*a + 1, 4*a, 2, 5*a + 5, 3*a + 5, 3*a + 1, 2*a, 2*a, 2*a + 4, 4*a + 2]]) 

sage: A.rational_form() 

[ a + 2| 0 0 0| 0 0 0 0 0 0 0] 

[-------+-----------------------+-------------------------------------------------------] 

[ 0| 0 0 a + 6| 0 0 0 0 0 0 0] 

[ 0| 1 0 6*a + 4| 0 0 0 0 0 0 0] 

[ 0| 0 1 6*a + 4| 0 0 0 0 0 0 0] 

[-------+-----------------------+-------------------------------------------------------] 

[ 0| 0 0 0| 0 0 0 0 0 0 2*a] 

[ 0| 0 0 0| 1 0 0 0 0 0 6*a + 3] 

[ 0| 0 0 0| 0 1 0 0 0 0 6*a + 1] 

[ 0| 0 0 0| 0 0 1 0 0 0 a + 2] 

[ 0| 0 0 0| 0 0 0 1 0 0 a + 6] 

[ 0| 0 0 0| 0 0 0 0 1 0 2*a + 1] 

[ 0| 0 0 0| 0 0 0 0 0 1 2*a + 1] 

sage: invariants = A.rational_form(format='invariants') 

sage: invariants 

[[6*a + 5, 1], [6*a + 1, a + 3, a + 3, 1], [5*a, a + 4, a + 6, 6*a + 5, 6*a + 1, 5*a + 6, 5*a + 6, 1]] 

sage: R.<x> = F[] 

sage: polys = [R(p) for p in invariants] 

sage: [p.factor() for p in polys] 

[x + 6*a + 5, (x + 6*a + 5) * (x^2 + (2*a + 5)*x + 5*a), (x + 6*a + 5) * (x^2 + (2*a + 5)*x + 5*a)^3] 

sage: polys[-1] == A.minimal_polynomial() 

True 

sage: prod(polys) == A.characteristic_polynomial() 

True 

sage: A.eigenvalues() 

Traceback (most recent call last): 

... 

NotImplementedError: algebraic closures of finite fields are only implemented for prime fields 

  

Companion matrices may be selected as any one of four different types. 

See the documentation for the companion matrix constructor, 

:meth:`sage.matrix.constructor.companion_matrix`, for more information. :: 

  

sage: A = matrix(QQ, [[35, -18, -2, -45], 

....: [22, -22, 12, -16], 

....: [ 5, -12, 12, 4], 

....: [16, -6, -4, -23]]) 

sage: A.rational_form(format='right') 

[ 2| 0 0 0] 

[--+--------] 

[ 0| 0 0 10] 

[ 0| 1 0 -1] 

[ 0| 0 1 0] 

sage: A.rational_form(format='bottom') 

[ 2| 0 0 0] 

[--+--------] 

[ 0| 0 1 0] 

[ 0| 0 0 1] 

[ 0|10 -1 0] 

sage: A.rational_form(format='left') 

[ 2| 0 0 0] 

[--+--------] 

[ 0| 0 1 0] 

[ 0|-1 0 1] 

[ 0|10 0 0] 

sage: A.rational_form(format='top') 

[ 2| 0 0 0] 

[--+--------] 

[ 0| 0 -1 10] 

[ 0| 1 0 0] 

[ 0| 0 1 0] 

  

TESTS:: 

  

sage: A = matrix(QQ, 2, 3, range(6)) 

sage: A.rational_form() 

Traceback (most recent call last): 

... 

TypeError: matrix must be square, not 2 x 3 

  

sage: A = matrix(Integers(6), 2, 2, range(4)) 

sage: A.rational_form() 

Traceback (most recent call last): 

... 

TypeError: matrix entries must come from an exact field, not Ring of integers modulo 6 

  

sage: A = matrix(RDF, 2, 2, range(4)) 

sage: A.rational_form() 

Traceback (most recent call last): 

... 

TypeError: matrix entries must come from an exact field, not Real Double Field 

  

sage: A = matrix(QQ, 2, range(4)) 

sage: A.rational_form(format='junk') 

Traceback (most recent call last): 

... 

ValueError: 'format' keyword must be 'right', 'bottom', 'left', 'top' or 'invariants', not junk 

  

sage: A = matrix(QQ, 2, range(4)) 

sage: A.rational_form(subdivide='garbage') 

Traceback (most recent call last): 

... 

ValueError: 'subdivide' keyword must be True or False, not garbage 

  

AUTHOR: 

  

- Rob Beezer (2011-06-09) 

""" 

from sage.arith.all import gcd 

import sage.rings.polynomial.polynomial_ring_constructor 

from sage.matrix.constructor import (block_diagonal_matrix, 

companion_matrix) 

  

R = self.base_ring() 

if not self.is_square(): 

raise TypeError("matrix must be square, not {0} x {1}".format(self.nrows(), self.ncols())) 

if not (R.is_field() and R.is_exact()): 

raise TypeError("matrix entries must come from an exact field, not {0}".format(R)) 

if format not in ['right', 'bottom', 'left', 'top', 'invariants']: 

raise ValueError("'format' keyword must be 'right', 'bottom', 'left', 'top' or 'invariants', not {0}".format(format)) 

if subdivide not in [True, False]: 

raise ValueError("'subdivide' keyword must be True or False, not {0}".format(subdivide)) 

  

_, polys, corners = self._zigzag_form(basis=False) 

cdef Py_ssize_t k = len(polys), j, i 

F = sage.rings.polynomial.polynomial_ring_constructor.PolynomialRing(R, 'x') 

cdef list C = [F(p) for p in polys] 

cdef list B = [b.is_one() for b in corners] 

B.append(False) # no last block, so no corner 

  

if B[0]: 

V = [F.one()] 

else: 

V = [F.zero()] 

  

for j in range(1, k): 

V[j-1] = gcd([V[j-1], C[j], C[j-1]]) 

for i in range(j-2, -1, -1): 

V[i] = gcd([V[i], V[i+1], C[i]]) 

m = -F.one() 

for i in range(j): 

g = gcd(m*V[i], C[i]) 

q, _ = C[i].quo_rem(g) 

C[i] = g 

if B[j]: 

_, V[i] = m.quo_rem(C[i]) 

else: 

V[i] = F.zero() 

m = m * q 

C[j] = m * C[j] 

if B[j]: 

V.append(m) 

else: 

V.append(F.zero()) 

  

# Leading constant polynomials in C are size zero blocks, so toss them 

# Massage remainder to have leading coefficient 1 

while C and not C[0].degree(): 

del C[0] 

for i in range(len(C)): 

unit = C[i].leading_coefficient() 

if not unit.is_one(): 

C[i] = ~unit*C[i] 

  

if format == 'invariants': 

inv = [] 

for poly in C: 

inv.append(poly.list()) 

return inv 

elif format in ['right', 'left', 'top', 'bottom']: 

companions = [] 

for poly in C: 

companions.append(companion_matrix(poly, format=format)) 

return block_diagonal_matrix(companions, subdivide=subdivide) 

  

# A limited number of access-only properties are provided for matrices 

@property 

def T(self): 

r""" 

Returns the transpose of a matrix. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, 5, range(25)) 

sage: A.T 

[ 0 5 10 15 20] 

[ 1 6 11 16 21] 

[ 2 7 12 17 22] 

[ 3 8 13 18 23] 

[ 4 9 14 19 24] 

""" 

return self.transpose() 

  

@property 

def C(self): 

r""" 

Returns the conjugate matrix. 

  

EXAMPLES:: 

  

sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I], 

....: [7 + 3*I, -1 + 6*I, 3 + 5*I], 

....: [3 + 3*I, -3 + 6*I, 5 + I]]) 

sage: A.C 

[ -3 5 + 3*I 7 + 4*I] 

[ 7 - 3*I -1 - 6*I 3 - 5*I] 

[ 3 - 3*I -3 - 6*I 5 - 1*I] 

  

""" 

return self.conjugate() 

  

@property 

def H(self): 

r""" 

Returns the conjugate-transpose (Hermitian) matrix. 

  

EXAMPLES:: 

  

sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I], 

....: [7 + 3*I, -1 + 6*I, 3 + 5*I], 

....: [3 + 3*I, -3 + 6*I, 5 + I]]) 

sage: A.H 

[ -3 7 - 3*I 3 - 3*I] 

[ 5 + 3*I -1 - 6*I -3 - 6*I] 

[ 7 + 4*I 3 - 5*I 5 - 1*I] 

""" 

return self.conjugate().transpose() 

  

@property 

def I(self): 

r""" 

Returns the inverse of the matrix, if it exists. 

  

EXAMPLES:: 

  

sage: A = matrix(QQ, [[-5, -3, -1, -7], 

....: [ 1, 1, 1, 0], 

....: [-1, -2, -2, 0], 

....: [-2, -1, 0, -4]]) 

sage: A.I 

doctest:...: DeprecationWarning: The I property on matrices has been deprecated. Please use the inverse() method instead. 

See http://trac.sagemath.org/20904 for details. 

[ 0 2 1 0] 

[-4 -8 -2 7] 

[ 4 7 1 -7] 

[ 1 1 0 -2] 

  

sage: B = matrix(QQ, [[-11, -5, 18, -6], 

....: [ 1, 2, -6, 8], 

....: [ -4, -2, 7, -3], 

....: [ 1, -2, 5, -11]]) 

sage: B.I 

Traceback (most recent call last): 

... 

ZeroDivisionError: input matrix must be nonsingular 

""" 

from sage.misc.superseded import deprecation 

deprecation(20904, "The I property on matrices has been deprecated. Please use the inverse() method instead.") 

return ~self 

  

def _smith_diag(d): 

r""" 

For internal use by the smith_form routine. Given a diagonal matrix d 

over a ring r, return matrices d', a,b such that a\*d\*b = d' and 

d' is diagonal with each entry dividing the next. 

  

If any of the d's is a unit, it replaces it with 1 (but no other 

attempt is made to pick "good" representatives of ideals). 

  

EXAMPLES:: 

  

sage: from sage.matrix.matrix2 import _smith_diag 

sage: OE = EquationOrder(x^2 - x + 2, 'w') 

sage: A = matrix(OE, 2, [2,0,0,3]) 

sage: D,U,V = _smith_diag(A); D,U,V 

( 

[1 0] [2 1] [ 1 -3] 

[0 6], [3 2], [-1 4] 

) 

sage: D == U*A*V 

True 

sage: m = matrix(GF(7),2, [3,0,0,6]); d,u,v = _smith_diag(m); d 

[1 0] 

[0 1] 

sage: u*m*v == d 

True 

""" 

  

dp = d.__copy__() 

n = min(d.nrows(), d.ncols()) 

R = d.base_ring() 

left = d.new_matrix(d.nrows(), d.nrows(), 1) 

right = d.new_matrix(d.ncols(), d.ncols(), 1) 

for i in xrange(n): 

I = R.ideal(dp[i,i]) 

  

if I == R.unit_ideal(): 

if dp[i,i] != 1: 

left.add_multiple_of_row(i,i,R(R(1)/(dp[i,i])) - 1) 

dp[i,i] = R(1) 

continue 

  

for j in xrange(i+1,n): 

if dp[j,j] not in I: 

t = R.ideal([dp[i,i], dp[j,j]]).gens_reduced() 

if len(t) > 1: raise ArithmeticError 

t = t[0] 

# find lambda, mu such that lambda*d[i,i] + mu*d[j,j] = t 

lamb = R(dp[i,i]/t).inverse_mod( R.ideal(dp[j,j]/t)) 

mu = R((t - lamb*dp[i,i]) / dp[j,j]) 

  

newlmat = dp.new_matrix(dp.nrows(), dp.nrows(), 1) 

newlmat[i,i] = lamb 

newlmat[i,j] = 1 

newlmat[j,i] = R(-dp[j,j]*mu/t) 

newlmat[j,j] = R(dp[i,i]/t) 

newrmat = dp.new_matrix(dp.ncols(), dp.ncols(), 1) 

newrmat[i,i] = 1 

newrmat[i,j] = R(-dp[j,j]/t) 

newrmat[j,i] = mu 

newrmat[j,j] = R(lamb*dp[i,i] / t) 

  

left = newlmat*left 

right = right*newrmat 

dp = newlmat*dp*newrmat 

return dp, left, right 

  

def _generic_clear_column(m): 

r""" 

Reduce the first column of m to canonical form -- that is, all entries 

below the first are nonzero -- by multiplying on the left by invertible 

matrices over the given base ring. This assumes that the base ring is a 

PID. Returns a pair (left, a) where left*self = a and a has first column in 

canonical form. 

  

If the first column is zero, then this function doesn't do anything very 

exciting. 

  

Used by the smith_form and hermite_form methods. 

  

EXAMPLES:: 

  

sage: L.<w> = NumberField(x^2 - x + 2) 

sage: OL = L.ring_of_integers(); w = OL(w) 

sage: m = matrix(OL, 8, 4, [2*w - 2, 2*w + 1, -2, w, 2, -2,-2*w - 2, -2*w + 2, -w + 2, 2*w + 1, -w + 2, -w - 2, -2*w, 2*w, -w+ 2, w - 1, -2*w + 2, 2*w + 2, 2*w - 1, -w, 2*w + 2, -w + 2, 2, 2*w -1, w - 4, -2*w - 2, 2*w - 1, 0, 6, 7, 2*w + 1, 14]) 

sage: s,t = m.echelon_form(transformation=True); t*m == s # indirect doctest 

True 

sage: s[0] 

(w, 0, 0, 0) 

""" 

if m.nrows() <= 1 or m.ncols() <= 0: 

return m.new_matrix(m.nrows(), m.nrows(), 1), m 

  

a = m.__copy__() 

left_mat = m.new_matrix(m.nrows(), m.nrows(), 1) 

R = m.base_ring() 

  

# case 1: if a_{0, 0} = 0 and a_{k, 0} != 0 for some k, swap rows 0 and k. 

if a[0, 0] == 0: 

k = 0 

while a[k, 0] == 0: 

k += 1 

if k == a.nrows(): # first column is zero 

return left_mat, a 

# k is now first row such that a[k, 0] is nonzero 

left_mat[0,0] = 0 

left_mat[k,k] = 0 

left_mat[0,k] = 1 

left_mat[k,0] = -1 

a = left_mat*a 

if left_mat * m != a: 

raise ArithmeticError("Something went wrong") 

  

# case 2: if there is an entry at position (k,j) such that a_{0,j} 

# does not divide a_{k,j}, then we know that there are c,d in R such 

# that c.a_{0,j} - d.a_{k,j} = B where B = gcd(a_{0,j}, a_{k,j}) (which 

# is well-defined since R is a PID). 

# Then for appropriate e,f the matrix 

# [c,-d] 

# [e,f] 

# is invertible over R 

  

if a[0,0] != 0: 

I = R.ideal(a[0, 0]) # need to make sure we change this when a[0,0] changes 

else: 

I = R.zero_ideal() 

for k in xrange(1, a.nrows()): 

if a[k,0] not in I: 

try: 

v = R.ideal(a[0,0], a[k,0]).gens_reduced() 

except Exception as msg: 

raise ArithmeticError("%s\nCan't create ideal on %s and %s" % (msg, a[0,0], a[k,0])) 

if len(v) > 1: 

raise ArithmeticError("Ideal %s not principal" % R.ideal(a[0,0], a[k,0])) 

B = v[0] 

  

# now we find c,d, using the fact that c * (a_{0,0}/B) - d * 

# (a_{k,0}/B) = 1, so c is the inverse of a_{0,0}/B modulo 

# a_{k,0}/B. 

# need to handle carefully the case when a_{k,0}/B is a unit, i.e. a_{k,0} divides 

# a_{0,0}. 

  

c = R(a[0,0] / B).inverse_mod(R.ideal(a[k,0] / B)) 

d = R( (c*a[0,0] - B)/(a[k,0]) ) 

  

# sanity check 

if c*a[0,0] - d*a[k,0] != B: 

raise ArithmeticError 

  

# now we find e,f such that e*d + c*f = 1 in the same way 

if c != 0: 

e = d.inverse_mod( R.ideal(c) ) 

f = R((1 - d*e)/c) 

else: 

e = R(-a[k,0]/B) # here d is a unit and this is just 1/d 

f = R(1) 

  

if e*d + c*f != 1: 

raise ArithmeticError 

newlmat = left_mat.parent()(1) 

newlmat[0,0] = c 

newlmat[0,k] = -d 

newlmat[k,0] = e 

newlmat[k,k] = f 

if newlmat.det() != 1: 

raise ArithmeticError 

a = newlmat*a 

I = R.ideal(a[0,0]) 

left_mat = newlmat*left_mat 

if left_mat * m != a: 

raise ArithmeticError 

  

# now everything in column 0 is divisible by the pivot 

for i in xrange(1,a.nrows()): 

s = R( a[i, 0]/a[0, 0]) 

a.add_multiple_of_row(i, 0, -s ) 

left_mat.add_multiple_of_row(i, 0, -s) 

if left_mat * m != a: 

raise ArithmeticError 

  

return left_mat, a 

  

def _smith_onestep(m): 

r""" 

Carry out one step of Smith normal form for matrix m. Returns three matrices a,b,c over 

the same base ring as m, such that a \* m \* c = b, a and c have 

determinant 1, and the zeroth row and column of b have no nonzero 

entries except b[0,0]. 

  

EXAMPLES:: 

  

sage: from sage.matrix.matrix2 import _smith_onestep 

sage: OE.<w> = EquationOrder(x^2 - x + 2) 

sage: m = matrix(OE, 3,3,[1,0,7,2,w, w+17, 13+8*w, 0, 6]) 

sage: a,b,c = _smith_onestep(m); b 

[ 1 0 0] 

[ 0 w w + 3] 

[ 0 0 -56*w - 85] 

sage: a * m * c == b 

True 

""" 

  

a = m.__copy__() 

left_mat = m.new_matrix(m.nrows(), m.nrows(), 1) 

right_mat = m.new_matrix(m.ncols(), m.ncols(), 1) 

  

if m == 0 or (m.nrows() <= 1 and m.ncols() <= 1): 

return left_mat, m, right_mat 

  

# preparation: if column 0 is zero, swap it with the first nonzero column 

j = 0 

while a.column(j) == 0: j += 1 

if j > 0: 

right_mat[0,0] = right_mat[j,j] = 0 

right_mat[0,j] = 1 

right_mat[j,0] = -1 

a = a*right_mat 

if m * right_mat != a: 

raise ArithmeticError 

  

left_mat, a = _generic_clear_column(a) 

assert left_mat * m * right_mat == a 

  

# test if everything to the right of the pivot in row 0 is good as well 

isdone = True 

for jj in xrange(j+1, a.ncols()): 

if a[0,jj] != 0: 

isdone = False 

  

# if not we recurse -- algorithm must terminate if R is Noetherian. 

if not isdone: 

s,t,u = _smith_onestep(a.transpose()) 

left_mat = u.transpose() * left_mat 

a = t.transpose() 

right_mat = right_mat* s.transpose() 

  

return left_mat, a, right_mat 

  

def decomp_seq(v): 

""" 

This function is used internally be the decomposition matrix 

method. It takes a list of tuples and produces a sequence that is 

correctly sorted and prints with carriage returns. 

  

EXAMPLES:: 

  

sage: from sage.matrix.matrix2 import decomp_seq 

sage: V = [(QQ^3, 2), (QQ^2, 1)] 

sage: decomp_seq(V) 

[ 

(Vector space of dimension 2 over Rational Field, 1), 

(Vector space of dimension 3 over Rational Field, 2) 

] 

""" 

list.sort(v, key=lambda x: x[0].dimension()) 

return Sequence(v, universe=tuple, check=False, cr=True) 

  

  

def _choose(Py_ssize_t n, Py_ssize_t t): 

""" 

Returns all possible sublists of length t from range(n) 

  

Based on algorithm T from Knuth's taocp part 4: 7.2.1.3 p.5 This 

function replaces the one based on algorithm L because it is 

faster. 

  

EXAMPLES:: 

  

sage: from sage.matrix.matrix2 import _choose 

sage: _choose(1,1) 

[[0]] 

sage: _choose(4,1) 

[[0], [1], [2], [3]] 

sage: _choose(4,4) 

[[0, 1, 2, 3]] 

  

AUTHORS: 

  

- Jaap Spies (2007-11-14) 

""" 

cdef Py_ssize_t j, temp 

  

x = [] # initialize T1 

c = list(xrange(t)) 

if t == n: 

x.append(c) 

return x 

c.append(n) 

c.append(0) 

j = t-1 

  

while True: 

x.append(c[:t]) # visit T2 

if j >= 0: 

c[j] = j+1 

j = j-1 

continue # goto T2 

  

if c[0]+1 < c[1]: # T3 easy case! 

c[0] = c[0]+1 

continue 

else: 

j = 1 

  

while True: 

c[j-1] = j-1 # T4 find j 

temp = c[j]+1 

if temp == c[j+1]: 

j = j+1 

else: 

break 

  

  

if j >= t: # T5 stop? 

break 

  

c[j] = temp # T6 

j = j-1 

  

return x 

  

def _binomial(Py_ssize_t n, Py_ssize_t k): 

""" 

Fast and unchecked implementation of binomial(n,k) This is only for 

internal use. 

  

EXAMPLES:: 

  

sage: from sage.matrix.matrix2 import _binomial 

sage: _binomial(10,2) 

45 

sage: _binomial(10,5) 

252 

  

AUTHORS: 

  

- Jaap Spies (2007-10-26) 

""" 

cdef Py_ssize_t i 

  

if 2 * k > n: 

k = n - k 

if k == 0: 

return 1 

  

result = n 

n, k = n - 1, k - 1 

i = 2 

while k > 0: 

result = (result * n) // i 

i, n, k = i + 1, n - 1, k - 1 

return result 

  

def _jordan_form_vector_in_difference(V, W): 

r""" 

Given two lists of vectors ``V`` and ``W`` over the same base field, 

returns a vector in the difference ``V - W``. If the difference is 

empty, returns ``None``. 

  

NOTES: 

  

This is meant to be a private helper method for the ``jordan_form`` method 

in the above class. 

  

TESTS:: 

  

sage: v = vector(ZZ, [1,0,0,0]) 

sage: w = vector(ZZ, [0,1,0,0]) 

sage: u = vector(ZZ, [1,1,0,0]) 

sage: sage.matrix.matrix2._jordan_form_vector_in_difference([v,w], [u]) 

(1, 0, 0, 0) 

""" 

if len(V) == 0: 

return None 

if len(W) == 0: 

return V[0] 

W_space = sage.all.span(W) 

for v in V: 

if v not in W_space: 

return v 

return None 

  

def _matrix_power_symbolic(A, n): 

r""" 

Return the symbolic `n`-th power `A^n` of the matrix `A` 

  

This function implements the computation of `A^n` for symbolic `n`, 

relying on the Jordan normal form of `A`, available for exact rings 

as :meth:`jordan_form`. See [Hig2008]_, §1.2, for further details. 

  

INPUT: 

  

- ``A`` -- a square matrix over an exact field 

  

- ``n`` -- a symbolic exponent 

  

OUTPUT: 

  

The matrix `A^n` (with symbolic entries involving the exponent). 

  

EXAMPLES: 

  

General power of a two by two matrix:: 

  

sage: n = SR.var('n') 

sage: A = matrix(QQ, [[2, -1], [1, 0]]) 

sage: B = A^n; B 

[ n + 1 -n] 

[ n -n + 1] 

sage: all(A^k == B.subs({n: k}) for k in range(8)) 

True 

  

General power of a three by three matrix in Jordan form:: 

  

sage: n = SR.var('n') 

sage: A = matrix(QQ, 3, [[2, 1, 0], [0, 2, 0], [0, 0, 3]]) 

sage: A 

[2 1 0] 

[0 2 0] 

[0 0 3] 

sage: B = A^n; B 

[ 2^n 2^(n - 1)*n 0] 

[ 0 2^n 0] 

[ 0 0 3^n] 

sage: all(A^k == B.subs({n: k}) for k in range(8)) 

True 

  

General power of a three by three matrix not in Jordan form:: 

  

sage: A = matrix([[4, 1, 2], [0, 2, -4], [0, 1, 6]]) 

sage: A 

[ 4 1 2] 

[ 0 2 -4] 

[ 0 1 6] 

sage: B = A^n; B 

[ 4^n 4^(n - 1)*n 2*4^(n - 1)*n] 

[ 0 -2*4^(n - 1)*n + 4^n -4*4^(n - 1)*n] 

[ 0 4^(n - 1)*n 2*4^(n - 1)*n + 4^n] 

sage: [B.subs({n: k}) for k in range(4)] 

[ 

[1 0 0] [ 4 1 2] [ 16 8 16] [ 64 48 96] 

[0 1 0] [ 0 2 -4] [ 0 0 -32] [ 0 -32 -192] 

[0 0 1], [ 0 1 6], [ 0 8 32], [ 0 48 160] 

] 

sage: all(A^k == B.subs({n: k}) for k in range(8)) 

True 

  

TESTS: 

  

Testing exponentiation in the symbolic ring:: 

  

sage: n = var('n') 

sage: A = matrix([[pi, e],[0, -2*I]]) 

sage: (A^n).list() 

[pi^n, 

-(-2*I)^n/(pi*e^(-1) + 2*I*e^(-1)) + pi^n/(pi*e^(-1) + 2*I*e^(-1)), 

0, 

(-2*I)^n] 

  

If the base ring is inexact, the Jordan normal form is not available:: 

  

sage: A = matrix(RDF, [[2, -1], [1, 0]]) 

sage: A^n 

Traceback (most recent call last): 

... 

ValueError: Jordan normal form not implemented over inexact rings. 

  

Testing exponentiation in the integer ring:: 

  

sage: A = matrix(ZZ, [[1,-1],[-1,1]]) 

sage: A^(2*n+1) 

[ 1/2*2^(2*n + 1) -1/2*2^(2*n + 1)] 

[-1/2*2^(2*n + 1) 1/2*2^(2*n + 1)] 

  

Check if :trac:`23215` is fixed:: 

  

sage: a, b, k = var('a, b, k') 

sage: (matrix(2, [a, b, -b, a])^k).list() 

[1/2*(a + I*b)^k + 1/2*(a - I*b)^k, 

-1/2*I*(a + I*b)^k + 1/2*I*(a - I*b)^k, 

1/2*I*(a + I*b)^k - 1/2*I*(a - I*b)^k, 

1/2*(a + I*b)^k + 1/2*(a - I*b)^k] 

""" 

from sage.rings.qqbar import AlgebraicNumber 

from sage.matrix.constructor import matrix 

from sage.functions.other import binomial 

from sage.symbolic.ring import SR 

from sage.rings.qqbar import QQbar 

  

got_SR = A.base_ring() == SR 

  

# Change to QQbar if possible 

try: 

A = A.change_ring(QQbar) 

except (TypeError, NotImplementedError): 

pass 

  

# Get Jordan matrix J and invertible matrix P such that A = P*J*~P 

# From that, we will compute M = J^n, and obtain A^n = P*J^n*~P 

J, P = A.jordan_form(transformation=True) 

  

# Where each Jordan block starts, and number of blocks 

block_start = [0] + J.subdivisions()[0] 

num_blocks = len(block_start) 

  

# Prepare matrix M to store `J^n`, computed by Jordan block 

M = matrix(SR, J.ncols()) 

M.subdivide(J.subdivisions()) 

  

for k in range(num_blocks): 

  

# Jordan block Jk, its dimension nk, the eigenvalue m 

Jk = J.subdivision(k, k) 

nk = Jk.ncols() 

mk = Jk[0,0] 

  

# First row of block Mk; its entries are of the form 

# D^i(f) / i! with f = x^n and D = differentiation wrt x 

if hasattr(mk, 'radical_expression'): 

mk = mk.radical_expression() 

vk = [(binomial(n, i) * mk**(n-i)).simplify_full() 

for i in range(nk)] 

  

# Form block Mk and insert it in M 

Mk = matrix(SR, [[SR.zero()]*i + vk[:nk-i] for i in range(nk)]) 

M.set_block(block_start[k], block_start[k], Mk) 

  

# Change entries of P and P^-1 into symbolic expressions 

if not got_SR: 

Pinv = (~P).apply_map(AlgebraicNumber.radical_expression) 

P = P.apply_map(AlgebraicNumber.radical_expression) 

else: 

Pinv = ~P 

  

return P * M * Pinv