passagemath-modules 10.5.46__cp310-cp310-macosx_14_0_arm64.whl → 10.6.20__cp310-cp310-macosx_14_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-modules might be problematic. Click here for more details.
- {passagemath_modules-10.5.46.dist-info → passagemath_modules-10.6.20.dist-info}/METADATA +49 -44
- {passagemath_modules-10.5.46.dist-info → passagemath_modules-10.6.20.dist-info}/RECORD +320 -314
- passagemath_modules.dylibs/libmpc.3.dylib +0 -0
- passagemath_modules.dylibs/libopenblasp-r0.3.29.dylib +0 -0
- sage/algebras/clifford_algebra.py +2 -2
- sage/algebras/clifford_algebra_element.cpython-310-darwin.so +0 -0
- sage/algebras/clifford_algebra_element.pyx +4 -2
- sage/algebras/exterior_algebra_groebner.cpython-310-darwin.so +0 -0
- sage/algebras/exterior_algebra_groebner.pyx +2 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +83 -5
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-310-darwin.so +0 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +2 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +28 -3
- sage/algebras/finite_gca.py +1 -1
- sage/algebras/lie_algebras/bgg_dual_module.py +18 -11
- sage/algebras/lie_algebras/classical_lie_algebra.py +3 -3
- sage/algebras/lie_algebras/examples.py +2 -2
- sage/algebras/lie_algebras/free_lie_algebra.py +1 -1
- sage/algebras/lie_algebras/heisenberg.py +4 -4
- sage/algebras/lie_algebras/lie_algebra.py +1 -1
- sage/algebras/lie_algebras/lie_algebra_element.cpython-310-darwin.so +0 -0
- sage/algebras/lie_algebras/lie_algebra_element.pyx +63 -27
- sage/algebras/lie_algebras/quotient.py +40 -29
- sage/algebras/lie_algebras/subalgebra.py +76 -53
- sage/algebras/lie_algebras/verma_module.py +1 -3
- sage/algebras/octonion_algebra.cpython-310-darwin.so +0 -0
- sage/algebras/octonion_algebra.pyx +1 -1
- sage/algebras/orlik_solomon.py +4 -4
- sage/algebras/orlik_terao.py +4 -4
- sage/algebras/steenrod/steenrod_algebra.py +37 -30
- sage/algebras/steenrod/steenrod_algebra_bases.py +2 -2
- sage/algebras/steenrod/steenrod_algebra_misc.py +4 -4
- sage/algebras/steenrod/steenrod_algebra_mult.py +2 -2
- sage/all__sagemath_modules.py +1 -0
- sage/calculus/integration.cpython-310-darwin.so +0 -0
- sage/calculus/integration.pyx +6 -5
- sage/calculus/interpolation.cpython-310-darwin.so +0 -0
- sage/calculus/interpolators.cpython-310-darwin.so +0 -0
- sage/calculus/ode.cpython-310-darwin.so +0 -0
- sage/calculus/ode.pxd +2 -2
- sage/calculus/ode.pyx +6 -4
- sage/calculus/riemann.cpython-310-darwin.so +0 -0
- sage/calculus/riemann.pyx +68 -48
- sage/calculus/transforms/dwt.cpython-310-darwin.so +0 -0
- sage/calculus/transforms/fft.cpython-310-darwin.so +0 -0
- sage/coding/ag_code_decoders.cpython-310-darwin.so +0 -0
- sage/coding/ag_code_decoders.pyx +31 -31
- sage/coding/binary_code.cpython-310-darwin.so +0 -0
- sage/coding/binary_code.pxd +6 -6
- sage/coding/binary_code.pyx +212 -173
- sage/coding/guruswami_sudan/utils.py +3 -5
- sage/coding/kasami_codes.cpython-310-darwin.so +0 -0
- sage/coding/kasami_codes.pyx +20 -24
- sage/coding/linear_code.py +2 -2
- sage/coding/linear_code_no_metric.py +5 -5
- sage/coding/linear_rank_metric.py +81 -19
- sage/combinat/free_module.py +22 -2
- sage/combinat/root_system/ambient_space.py +1 -1
- sage/combinat/root_system/associahedron.py +4 -4
- sage/combinat/root_system/braid_move_calculator.py +1 -1
- sage/combinat/root_system/braid_orbit.cpython-310-darwin.so +0 -0
- sage/combinat/root_system/branching_rules.py +2 -2
- sage/combinat/root_system/cartan_type.py +14 -14
- sage/combinat/root_system/coxeter_group.py +2 -2
- sage/combinat/root_system/coxeter_type.py +11 -0
- sage/combinat/root_system/extended_affine_weyl_group.py +8 -8
- sage/combinat/root_system/fundamental_group.py +2 -4
- sage/combinat/root_system/hecke_algebra_representation.py +1 -1
- sage/combinat/root_system/pieri_factors.py +2 -2
- sage/combinat/root_system/root_lattice_realization_algebras.py +1 -1
- sage/combinat/root_system/root_lattice_realizations.py +1 -1
- sage/combinat/root_system/type_folded.py +3 -3
- sage/combinat/root_system/type_reducible.py +8 -7
- sage/combinat/root_system/type_super_A.py +2 -2
- sage/combinat/root_system/weight_lattice_realizations.py +9 -8
- sage/combinat/root_system/weyl_characters.py +1 -1
- sage/crypto/__init__.py +1 -0
- sage/crypto/block_cipher/des.py +1 -1
- sage/crypto/block_cipher/miniaes.py +3 -3
- sage/crypto/block_cipher/present.py +3 -3
- sage/crypto/block_cipher/sdes.py +3 -3
- sage/crypto/boolean_function.cpython-310-darwin.so +0 -0
- sage/crypto/boolean_function.pyx +22 -23
- sage/crypto/key_exchange/diffie_hellman.py +4 -9
- sage/crypto/mq/sr.py +1 -1
- sage/crypto/public_key/blum_goldwasser.py +3 -3
- sage/crypto/sbox.cpython-310-darwin.so +0 -0
- sage/crypto/sbox.pyx +1 -1
- sage/crypto/sboxes.py +22 -0
- sage/crypto/util.py +4 -6
- sage/ext/interpreters/__init__.py +1 -1
- sage/ext/interpreters/all__sagemath_modules.py +1 -1
- sage/ext/interpreters/wrapper_cc.cpython-310-darwin.so +0 -0
- sage/ext/interpreters/wrapper_cc.pxd +5 -5
- sage/ext/interpreters/wrapper_cc.pyx +1 -1
- sage/ext/interpreters/wrapper_cdf.cpython-310-darwin.so +0 -0
- sage/ext/interpreters/wrapper_cdf.pxd +5 -7
- sage/ext/interpreters/wrapper_cdf.pyx +4 -10
- sage/ext/interpreters/wrapper_rdf.cpython-310-darwin.so +0 -0
- sage/ext/interpreters/wrapper_rdf.pxd +1 -1
- sage/ext/interpreters/wrapper_rdf.pyx +1 -1
- sage/ext/interpreters/wrapper_rr.cpython-310-darwin.so +0 -0
- sage/ext/interpreters/wrapper_rr.pxd +5 -5
- sage/ext/interpreters/wrapper_rr.pyx +1 -2
- sage/geometry/toric_lattice.py +3 -3
- sage/geometry/toric_lattice_element.cpython-310-darwin.so +0 -0
- sage/groups/additive_abelian/additive_abelian_group.py +1 -1
- sage/groups/additive_abelian/qmodnz.py +4 -4
- sage/groups/matrix_gps/coxeter_group.py +17 -4
- sage/groups/matrix_gps/group_element.cpython-310-darwin.so +0 -0
- sage/groups/misc_gps/argument_groups.py +2 -2
- sage/groups/misc_gps/imaginary_groups.py +4 -4
- sage/groups/perm_gps/partn_ref/refinement_binary.cpython-310-darwin.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-310-darwin.so +0 -0
- sage/homology/chain_complex.py +0 -2
- sage/homology/hochschild_complex.py +3 -3
- sage/homology/homology_morphism.py +6 -6
- sage/homology/homology_vector_space_with_basis.py +1 -1
- sage/libs/gsl/array.cpython-310-darwin.so +0 -0
- sage/libs/mpmath/utils.cpython-310-darwin.so +0 -0
- sage/matrix/action.cpython-310-darwin.so +0 -0
- sage/matrix/args.cpython-310-darwin.so +0 -0
- sage/matrix/args.pyx +25 -10
- sage/matrix/benchmark.py +8 -4
- sage/matrix/compute_J_ideal.py +2 -2
- sage/matrix/constructor.cpython-310-darwin.so +0 -0
- sage/matrix/echelon_matrix.cpython-310-darwin.so +0 -0
- sage/matrix/echelon_matrix.pyx +1 -1
- sage/matrix/matrix0.cpython-310-darwin.so +0 -0
- sage/matrix/matrix0.pxd +3 -3
- sage/matrix/matrix0.pyx +7 -5
- sage/matrix/matrix1.cpython-310-darwin.so +0 -0
- sage/matrix/matrix1.pyx +87 -48
- sage/matrix/matrix2.cpython-310-darwin.so +0 -0
- sage/matrix/matrix2.pxd +3 -3
- sage/matrix/matrix2.pyx +758 -75
- sage/matrix/matrix_cdv.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_complex_double_dense.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_complex_double_dense.pyx +1 -1
- sage/matrix/matrix_dense.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_dense.pyx +2 -3
- sage/matrix/matrix_double_dense.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_double_dense.pyx +11 -5
- sage/matrix/matrix_double_sparse.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_generic_dense.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_generic_sparse.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_generic_sparse.pyx +1 -1
- sage/matrix/matrix_laurent_mpolynomial_dense.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_numpy_dense.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_numpy_integer_dense.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_polynomial_dense.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_polynomial_dense.pyx +952 -261
- sage/matrix/matrix_real_double_dense.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_sparse.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_sparse.pyx +2 -3
- sage/matrix/matrix_window.cpython-310-darwin.so +0 -0
- sage/matrix/matrix_window.pyx +2 -2
- sage/matrix/misc_mpfr.cpython-310-darwin.so +0 -0
- sage/matrix/operation_table.py +0 -2
- sage/matrix/special.py +4 -0
- sage/matrix/strassen.cpython-310-darwin.so +0 -0
- sage/matrix/strassen.pyx +1 -1
- sage/matroids/basis_exchange_matroid.cpython-310-darwin.so +0 -0
- sage/matroids/basis_matroid.cpython-310-darwin.so +0 -0
- sage/matroids/chow_ring.py +68 -65
- sage/matroids/chow_ring_ideal.py +41 -38
- sage/matroids/circuit_closures_matroid.cpython-310-darwin.so +0 -0
- sage/matroids/circuits_matroid.cpython-310-darwin.so +0 -0
- sage/matroids/database_matroids.py +16 -5
- sage/matroids/dual_matroid.py +2 -2
- sage/matroids/extension.cpython-310-darwin.so +0 -0
- sage/matroids/flats_matroid.cpython-310-darwin.so +0 -0
- sage/matroids/gammoid.py +1 -1
- sage/matroids/graphic_matroid.cpython-310-darwin.so +0 -0
- sage/matroids/graphic_matroid.pyx +3 -3
- sage/matroids/lean_matrix.cpython-310-darwin.so +0 -0
- sage/matroids/lean_matrix.pyx +22 -22
- sage/matroids/linear_matroid.cpython-310-darwin.so +0 -0
- sage/matroids/linear_matroid.pyx +13 -13
- sage/matroids/matroid.cpython-310-darwin.so +0 -0
- sage/matroids/matroid.pyx +15 -15
- sage/matroids/matroids_plot_helpers.py +48 -46
- sage/matroids/minor_matroid.py +2 -2
- sage/matroids/set_system.cpython-310-darwin.so +0 -0
- sage/matroids/transversal_matroid.cpython-310-darwin.so +0 -0
- sage/matroids/transversal_matroid.pyx +3 -3
- sage/matroids/union_matroid.cpython-310-darwin.so +0 -0
- sage/matroids/union_matroid.pyx +3 -0
- sage/matroids/unpickling.cpython-310-darwin.so +0 -0
- sage/matroids/utilities.py +2 -2
- sage/misc/c3.cpython-310-darwin.so +0 -0
- sage/misc/compat.py +1 -2
- sage/misc/pickle_old.cpython-310-darwin.so +0 -0
- sage/modules/diamond_cutting.py +117 -30
- sage/modules/fg_pid/fgp_module.py +3 -3
- sage/modules/filtered_vector_space.py +4 -4
- sage/modules/finite_submodule_iter.cpython-310-darwin.so +0 -0
- sage/modules/fp_graded/free_module.py +2 -2
- sage/modules/fp_graded/module.py +2 -2
- sage/modules/fp_graded/morphism.py +4 -4
- sage/modules/fp_graded/steenrod/morphism.py +1 -1
- sage/modules/free_module.py +144 -15
- sage/modules/free_module_element.cpython-310-darwin.so +0 -0
- sage/modules/free_module_element.pyx +4 -4
- sage/modules/free_module_integer.py +2 -2
- sage/modules/free_module_morphism.py +3 -3
- sage/modules/free_module_pseudohomspace.py +352 -0
- sage/modules/free_module_pseudomorphism.py +578 -0
- sage/modules/free_quadratic_module_integer_symmetric.py +24 -13
- sage/modules/matrix_morphism.py +9 -9
- sage/modules/multi_filtered_vector_space.py +4 -4
- sage/modules/ore_module.py +2208 -0
- sage/modules/ore_module_element.py +178 -0
- sage/modules/ore_module_homspace.py +147 -0
- sage/modules/ore_module_morphism.py +968 -0
- sage/modules/quotient_module.py +11 -1
- sage/modules/submodule.py +1 -1
- sage/modules/torsion_quadratic_module.py +1 -1
- sage/modules/vector_complex_double_dense.cpython-310-darwin.so +0 -0
- sage/modules/vector_double_dense.cpython-310-darwin.so +0 -0
- sage/modules/vector_integer_dense.cpython-310-darwin.so +0 -0
- sage/modules/vector_integer_sparse.cpython-310-darwin.so +0 -0
- sage/modules/vector_integer_sparse.pyx +4 -4
- sage/modules/vector_modn_dense.cpython-310-darwin.so +0 -0
- sage/modules/vector_modn_sparse.cpython-310-darwin.so +0 -0
- sage/modules/vector_numpy_dense.cpython-310-darwin.so +0 -0
- sage/modules/vector_numpy_integer_dense.cpython-310-darwin.so +0 -0
- sage/modules/vector_rational_dense.cpython-310-darwin.so +0 -0
- sage/modules/vector_rational_dense.pyx +1 -1
- sage/modules/vector_rational_sparse.cpython-310-darwin.so +0 -0
- sage/modules/vector_rational_sparse.pyx +5 -5
- sage/modules/vector_real_double_dense.cpython-310-darwin.so +0 -0
- sage/modules/vector_space_morphism.py +2 -2
- sage/modules/with_basis/cell_module.py +17 -0
- sage/modules/with_basis/indexed_element.cpython-310-darwin.so +0 -0
- sage/modules/with_basis/indexed_element.pyx +1 -1
- sage/modules/with_basis/invariant.py +1 -1
- sage/modules/with_basis/representation.py +0 -1
- sage/modules/with_basis/subquotient.py +2 -2
- sage/numerical/gauss_legendre.cpython-310-darwin.so +0 -0
- sage/probability/probability_distribution.cpython-310-darwin.so +0 -0
- sage/quadratic_forms/binary_qf.py +7 -7
- sage/quadratic_forms/bqf_class_group.py +26 -92
- sage/quadratic_forms/count_local_2.cpython-310-darwin.so +0 -0
- sage/quadratic_forms/extras.py +1 -1
- sage/quadratic_forms/quadratic_form.py +5 -4
- sage/quadratic_forms/quadratic_form__equivalence_testing.py +7 -4
- sage/quadratic_forms/quadratic_form__evaluate.cpython-310-darwin.so +0 -0
- sage/quadratic_forms/quadratic_form__local_field_invariants.py +10 -10
- sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +2 -2
- sage/quadratic_forms/ternary.cpython-310-darwin.so +0 -0
- sage/quadratic_forms/ternary_qf.py +50 -83
- sage/rings/complex_conversion.cpython-310-darwin.so +0 -0
- sage/rings/complex_double.cpython-310-darwin.so +0 -0
- sage/rings/complex_double.pxd +1 -0
- sage/rings/complex_double.pyx +37 -32
- sage/rings/complex_mpc.cpython-310-darwin.so +0 -0
- sage/rings/complex_mpc.pyx +27 -23
- sage/rings/complex_mpfr.cpython-310-darwin.so +0 -0
- sage/rings/complex_mpfr.pyx +11 -9
- sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +277 -21
- sage/rings/function_field/drinfeld_modules/drinfeld_module.py +10 -1
- sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1 -1
- sage/rings/function_field/drinfeld_modules/homset.py +1 -2
- sage/rings/function_field/drinfeld_modules/morphism.py +2 -2
- sage/rings/function_field/hermite_form_polynomial.cpython-310-darwin.so +0 -0
- sage/rings/function_field/khuri_makdisi.cpython-310-darwin.so +0 -0
- sage/rings/function_field/khuri_makdisi.pyx +27 -25
- sage/rings/invariants/invariant_theory.py +61 -60
- sage/rings/invariants/reconstruction.py +8 -8
- sage/rings/polynomial/laurent_polynomial_mpair.cpython-310-darwin.so +0 -0
- sage/rings/polynomial/ore_function_element.py +1 -1
- sage/rings/polynomial/ore_polynomial_element.cpython-310-darwin.so +0 -0
- sage/rings/polynomial/ore_polynomial_element.pyx +8 -8
- sage/rings/polynomial/ore_polynomial_ring.py +134 -17
- sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-310-darwin.so +0 -0
- sage/rings/polynomial/skew_polynomial_element.cpython-310-darwin.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_field.cpython-310-darwin.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pyx +3 -4
- sage/rings/polynomial/skew_polynomial_finite_order.cpython-310-darwin.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pyx +2 -5
- sage/rings/real_double_element_gsl.cpython-310-darwin.so +0 -0
- sage/rings/real_mpfr.cpython-310-darwin.so +0 -0
- sage/rings/real_mpfr.pyx +25 -7
- sage/rings/ring_extension.cpython-310-darwin.so +0 -0
- sage/rings/ring_extension.pyx +4 -2
- sage/rings/ring_extension_conversion.cpython-310-darwin.so +0 -0
- sage/rings/ring_extension_element.cpython-310-darwin.so +0 -0
- sage/rings/ring_extension_element.pyx +42 -0
- sage/rings/ring_extension_morphism.cpython-310-darwin.so +0 -0
- sage/schemes/projective/cohomology.py +2 -2
- sage/stats/basic_stats.py +9 -6
- sage/stats/distributions/dgs_misc.h +11 -4
- sage/stats/distributions/discrete_gaussian_integer.cpython-310-darwin.so +0 -0
- sage/stats/distributions/discrete_gaussian_integer.pyx +9 -7
- sage/stats/hmm/chmm.cpython-310-darwin.so +0 -0
- sage/stats/hmm/chmm.pyx +13 -13
- sage/stats/hmm/distributions.cpython-310-darwin.so +0 -0
- sage/stats/hmm/distributions.pxd +3 -3
- sage/stats/hmm/distributions.pyx +3 -3
- sage/stats/hmm/hmm.cpython-310-darwin.so +0 -0
- sage/stats/hmm/hmm.pxd +3 -3
- sage/stats/hmm/hmm.pyx +6 -6
- sage/stats/hmm/util.cpython-310-darwin.so +0 -0
- sage/stats/hmm/util.pyx +6 -6
- sage/stats/intlist.cpython-310-darwin.so +0 -0
- sage/stats/intlist.pxd +3 -3
- sage/stats/time_series.cpython-310-darwin.so +0 -0
- sage/tensor/modules/alternating_contr_tensor.py +3 -3
- sage/tensor/modules/comp.py +3 -3
- sage/tensor/modules/ext_pow_free_module.py +3 -3
- sage/tensor/modules/format_utilities.py +3 -3
- sage/tensor/modules/free_module_linear_group.py +3 -3
- sage/tensor/modules/free_module_morphism.py +0 -1
- sage/tensor/modules/tensor_free_module.py +3 -3
- sage/tensor/modules/tensor_free_submodule.py +1 -1
- sage/tensor/modules/tensor_free_submodule_basis.py +1 -1
- sage/tensor/modules/tensor_with_indices.py +5 -5
- {passagemath_modules-10.5.46.dist-info → passagemath_modules-10.6.20.dist-info}/WHEEL +0 -0
- {passagemath_modules-10.5.46.dist-info → passagemath_modules-10.6.20.dist-info}/top_level.txt +0 -0
sage/matrix/matrix2.pyx
CHANGED
|
@@ -1545,13 +1545,11 @@ cdef class Matrix(Matrix1):
|
|
|
1545
1545
|
m = self._nrows
|
|
1546
1546
|
n = self._ncols
|
|
1547
1547
|
if not m <= n:
|
|
1548
|
-
raise ValueError("must have m <= n, but m (
|
|
1548
|
+
raise ValueError(f"must have m <= n, but m (={m}) and n (={n})")
|
|
1549
1549
|
|
|
1550
1550
|
for r from 1 <= r < m+1:
|
|
1551
1551
|
lst = _choose(n, r)
|
|
1552
|
-
tmp = []
|
|
1553
|
-
for cols in lst:
|
|
1554
|
-
tmp.append(self.prod_of_row_sums(cols))
|
|
1552
|
+
tmp = [self.prod_of_row_sums(cols) for cols in lst]
|
|
1555
1553
|
s = sum(tmp)
|
|
1556
1554
|
# sn = (-1)^(m-r)
|
|
1557
1555
|
if (m - r) % 2 == 0:
|
|
@@ -1889,7 +1887,7 @@ cdef class Matrix(Matrix1):
|
|
|
1889
1887
|
|
|
1890
1888
|
The number of derangements of length `n` is the permanent
|
|
1891
1889
|
of a matrix with 0 on the diagonal and 1 elsewhere;
|
|
1892
|
-
for `n=21` it is `18795307255050944540` (see :oeis:`A000166`)
|
|
1890
|
+
for `n=21` it is `18795307255050944540` (see :oeis:`A000166`)::
|
|
1893
1891
|
|
|
1894
1892
|
sage: A = identity_matrix(21)
|
|
1895
1893
|
sage: A.rook_vector(complement=True)[-1]
|
|
@@ -3291,6 +3289,16 @@ cdef class Matrix(Matrix1):
|
|
|
3291
3289
|
sage: A._charpoly_df()
|
|
3292
3290
|
x^3 + 8*x^2 + 10*x + 1
|
|
3293
3291
|
|
|
3292
|
+
.. NOTE::
|
|
3293
|
+
|
|
3294
|
+
The key feature of this implementation is that it is division-free.
|
|
3295
|
+
This means that it can be used as a generic implementation for any
|
|
3296
|
+
ring (commutative and with multiplicative identity). The algorithm
|
|
3297
|
+
is described in full detail as Algorithm 3.1 in [Sei2002]_.
|
|
3298
|
+
|
|
3299
|
+
Note that there is a missing minus sign in front of the last term in
|
|
3300
|
+
the penultimate line of Algorithm 3.1.
|
|
3301
|
+
|
|
3294
3302
|
TESTS::
|
|
3295
3303
|
|
|
3296
3304
|
sage: A = matrix(ZZ, 0, 0)
|
|
@@ -3309,15 +3317,11 @@ cdef class Matrix(Matrix1):
|
|
|
3309
3317
|
sage: matrix(4, 4, lambda i, j: R.an_element())._charpoly_df() # needs sage.combinat
|
|
3310
3318
|
B[1]*x^4 - 4*B[u]*x^3
|
|
3311
3319
|
|
|
3312
|
-
|
|
3320
|
+
Test that the function is interruptible::
|
|
3313
3321
|
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
is described in full detail as Algorithm 3.1 in [Sei2002]_.
|
|
3318
|
-
|
|
3319
|
-
Note that there is a missing minus sign in front of the last term in
|
|
3320
|
-
the penultimate line of Algorithm 3.1.
|
|
3322
|
+
sage: m = matrix.random(RR, 128)
|
|
3323
|
+
sage: from sage.doctest.util import ensure_interruptible_after
|
|
3324
|
+
sage: with ensure_interruptible_after(1): m.charpoly()
|
|
3321
3325
|
"""
|
|
3322
3326
|
|
|
3323
3327
|
# Validate assertions
|
|
@@ -3374,6 +3378,7 @@ cdef class Matrix(Matrix1):
|
|
|
3374
3378
|
for j in range(t+1):
|
|
3375
3379
|
s = s + M.get_unsafe(i, j) * a.get_unsafe(p-1, j)
|
|
3376
3380
|
a.set_unsafe(p, i, s)
|
|
3381
|
+
sig_check()
|
|
3377
3382
|
|
|
3378
3383
|
# Set A[p, t] to be the (t)th entry in a[p, t]
|
|
3379
3384
|
A[p] = a.get_unsafe(p, t)
|
|
@@ -3480,10 +3485,17 @@ cdef class Matrix(Matrix1):
|
|
|
3480
3485
|
raise TypeError("lcm function not defined for elements of the base ring")
|
|
3481
3486
|
return d
|
|
3482
3487
|
|
|
3483
|
-
def diagonal(self):
|
|
3488
|
+
def diagonal(self, offset=0):
|
|
3484
3489
|
r"""
|
|
3485
3490
|
Return the diagonal entries of ``self``.
|
|
3486
3491
|
|
|
3492
|
+
INPUT:
|
|
3493
|
+
|
|
3494
|
+
- ``offset`` -- integer (default: ``0``); parameter pointing diagonal
|
|
3495
|
+
parallel to the main diagonal. The main diagonal is the one with
|
|
3496
|
+
offset 0. The diagonals above have positive offsets and the diagonals
|
|
3497
|
+
below have negative offsets.
|
|
3498
|
+
|
|
3487
3499
|
OUTPUT:
|
|
3488
3500
|
|
|
3489
3501
|
A list containing the entries of the matrix that
|
|
@@ -3506,6 +3518,16 @@ cdef class Matrix(Matrix1):
|
|
|
3506
3518
|
[14 15 16 17 18 19 20]
|
|
3507
3519
|
sage: B.diagonal()
|
|
3508
3520
|
[0, 8, 16]
|
|
3521
|
+
sage: B.diagonal(1)
|
|
3522
|
+
[1, 9, 17]
|
|
3523
|
+
sage: B.diagonal(-1)
|
|
3524
|
+
[7, 15]
|
|
3525
|
+
sage: B.diagonal(-2)
|
|
3526
|
+
[14]
|
|
3527
|
+
sage: B.diagonal(100) # when idx out of range
|
|
3528
|
+
[]
|
|
3529
|
+
sage: B.diagonal(-100)
|
|
3530
|
+
[]
|
|
3509
3531
|
|
|
3510
3532
|
sage: C = matrix(3, 2, range(6)); C
|
|
3511
3533
|
[0 1]
|
|
@@ -3513,6 +3535,10 @@ cdef class Matrix(Matrix1):
|
|
|
3513
3535
|
[4 5]
|
|
3514
3536
|
sage: C.diagonal()
|
|
3515
3537
|
[0, 3]
|
|
3538
|
+
sage: C.diagonal(-1)
|
|
3539
|
+
[2, 5]
|
|
3540
|
+
sage: C.diagonal(1)
|
|
3541
|
+
[1]
|
|
3516
3542
|
|
|
3517
3543
|
Empty matrices behave properly. ::
|
|
3518
3544
|
|
|
@@ -3521,8 +3547,11 @@ cdef class Matrix(Matrix1):
|
|
|
3521
3547
|
sage: E.diagonal()
|
|
3522
3548
|
[]
|
|
3523
3549
|
"""
|
|
3524
|
-
|
|
3525
|
-
|
|
3550
|
+
if offset >= 0:
|
|
3551
|
+
n = min(self.nrows(), self.ncols() - offset)
|
|
3552
|
+
return [self[i, i + offset] for i in range(n)]
|
|
3553
|
+
n = min(self.nrows() + offset, self.ncols())
|
|
3554
|
+
return [self[i - offset, i] for i in range(n)]
|
|
3526
3555
|
|
|
3527
3556
|
def trace(self):
|
|
3528
3557
|
"""
|
|
@@ -3579,6 +3608,42 @@ cdef class Matrix(Matrix1):
|
|
|
3579
3608
|
s += self.get_unsafe(i, j) * other.get_unsafe(j, i)
|
|
3580
3609
|
return s
|
|
3581
3610
|
|
|
3611
|
+
def get_bandwidth(self):
|
|
3612
|
+
"""
|
|
3613
|
+
Return the bandwidth of ``self``, which is the maximum `i` such that
|
|
3614
|
+
the `i` superdiagonal or subdiagonal contains a nonzero entry.
|
|
3615
|
+
|
|
3616
|
+
EXAMPLES::
|
|
3617
|
+
|
|
3618
|
+
sage: A = matrix([[1,0,0],[0,1,0],[0,0,1]]); A
|
|
3619
|
+
[1 0 0]
|
|
3620
|
+
[0 1 0]
|
|
3621
|
+
[0 0 1]
|
|
3622
|
+
sage: A.get_bandwidth()
|
|
3623
|
+
0
|
|
3624
|
+
|
|
3625
|
+
sage: B = matrix([[1,2,3],[0,4,5],[0,0,6]]); B
|
|
3626
|
+
[1 2 3]
|
|
3627
|
+
[0 4 5]
|
|
3628
|
+
[0 0 6]
|
|
3629
|
+
sage: B.get_bandwidth()
|
|
3630
|
+
2
|
|
3631
|
+
|
|
3632
|
+
sage: C = matrix(3, 2, range(6)); C
|
|
3633
|
+
[0 1]
|
|
3634
|
+
[2 3]
|
|
3635
|
+
[4 5]
|
|
3636
|
+
sage: C.get_bandwidth()
|
|
3637
|
+
2
|
|
3638
|
+
"""
|
|
3639
|
+
cdef Py_ssize_t i
|
|
3640
|
+
diag_range = max(self.nrows(), self.ncols()) - 1
|
|
3641
|
+
|
|
3642
|
+
for i in range(diag_range, 0, -1):
|
|
3643
|
+
if any(self.diagonal(i)) or any(self.diagonal(-i)):
|
|
3644
|
+
return ZZ(i)
|
|
3645
|
+
return ZZ.zero()
|
|
3646
|
+
|
|
3582
3647
|
#####################################################################################
|
|
3583
3648
|
# Generic Hessenberg Form and charpoly algorithm
|
|
3584
3649
|
#####################################################################################
|
|
@@ -3615,7 +3680,7 @@ cdef class Matrix(Matrix1):
|
|
|
3615
3680
|
H = self.change_ring(K)
|
|
3616
3681
|
H.hessenbergize()
|
|
3617
3682
|
except TypeError as msg:
|
|
3618
|
-
raise TypeError("%s\nHessenberg form only possible for matrices over a field"%msg)
|
|
3683
|
+
raise TypeError("%s\nHessenberg form only possible for matrices over a field" % msg)
|
|
3619
3684
|
else:
|
|
3620
3685
|
H = self.__copy__()
|
|
3621
3686
|
H.hessenbergize()
|
|
@@ -4596,6 +4661,7 @@ cdef class Matrix(Matrix1):
|
|
|
4596
4661
|
The "usual" quaternions are a non-commutative ring and computations
|
|
4597
4662
|
of kernels over these rings are not implemented. ::
|
|
4598
4663
|
|
|
4664
|
+
sage: # needs sage.libs.singular
|
|
4599
4665
|
sage: Q.<i,j,k> = QuaternionAlgebra(-1,-1)
|
|
4600
4666
|
sage: A = matrix(Q, 2, [i,j,-1,k])
|
|
4601
4667
|
sage: A.right_kernel_matrix()
|
|
@@ -5046,6 +5112,7 @@ cdef class Matrix(Matrix1):
|
|
|
5046
5112
|
Matrices over non-commutative rings are not a good idea either.
|
|
5047
5113
|
These are the "usual" quaternions. ::
|
|
5048
5114
|
|
|
5115
|
+
sage: # needs sage.libs.singular
|
|
5049
5116
|
sage: Q.<i,j,k> = QuaternionAlgebra(-1,-1)
|
|
5050
5117
|
sage: A = matrix(Q, 2, [i,j,-1,k])
|
|
5051
5118
|
sage: A.right_kernel()
|
|
@@ -5690,7 +5757,7 @@ cdef class Matrix(Matrix1):
|
|
|
5690
5757
|
return X, Y
|
|
5691
5758
|
return X
|
|
5692
5759
|
else:
|
|
5693
|
-
raise ValueError("no algorithm '%s'"%algorithm)
|
|
5760
|
+
raise ValueError("no algorithm '%s'" % algorithm)
|
|
5694
5761
|
|
|
5695
5762
|
def _decomposition_spin_generic(self, is_diagonalizable=False):
|
|
5696
5763
|
r"""
|
|
@@ -5753,14 +5820,16 @@ cdef class Matrix(Matrix1):
|
|
|
5753
5820
|
v = h.list()
|
|
5754
5821
|
|
|
5755
5822
|
while len(S) < tries:
|
|
5756
|
-
t = verbose('%s-spinning %s-th random vector'%(num_iterates, len(S)),
|
|
5823
|
+
t = verbose('%s-spinning %s-th random vector' % (num_iterates, len(S)),
|
|
5824
|
+
level=2, caller_name='generic spin decomp')
|
|
5757
5825
|
S.append(self.iterates(V.random_element(), num_iterates))
|
|
5758
|
-
verbose('done spinning',
|
|
5826
|
+
verbose('done spinning',
|
|
5827
|
+
level=2, t=t, caller_name='generic spin decomp')
|
|
5759
5828
|
|
|
5760
5829
|
for j in range(0 if W is None else W.nrows() // g.degree(), len(S)):
|
|
5761
5830
|
# Compute one element of the kernel of g(A)**m.
|
|
5762
|
-
t = verbose('compute element of kernel of g(A), for g of degree %s'%g.degree(),
|
|
5763
|
-
caller_name='generic spin decomp')
|
|
5831
|
+
t = verbose('compute element of kernel of g(A), for g of degree %s' % g.degree(),
|
|
5832
|
+
level=2, caller_name='generic spin decomp')
|
|
5764
5833
|
w = S[j].linear_combination_of_rows(h.list())
|
|
5765
5834
|
t = verbose('done computing element of kernel of g(A)', t=t, level=2, caller_name='generic spin decomp')
|
|
5766
5835
|
|
|
@@ -5779,7 +5848,7 @@ cdef class Matrix(Matrix1):
|
|
|
5779
5848
|
verbose('computed row space', level=2, t=t, caller_name='generic spin decomp')
|
|
5780
5849
|
break
|
|
5781
5850
|
else:
|
|
5782
|
-
verbose('we have not yet generated all the kernel (rank so far=%s, target rank=%s)'%(
|
|
5851
|
+
verbose('we have not yet generated all the kernel (rank so far=%s, target rank=%s)' % (
|
|
5783
5852
|
W.rank(), m*g.degree()), level=2, caller_name='generic spin decomp')
|
|
5784
5853
|
tries += 1
|
|
5785
5854
|
if tries > 1000*m: # avoid an insanely long infinite loop
|
|
@@ -5815,12 +5884,13 @@ cdef class Matrix(Matrix1):
|
|
|
5815
5884
|
return decomp_seq([(V, m==1)])
|
|
5816
5885
|
F.sort()
|
|
5817
5886
|
for g, m in f.factor():
|
|
5818
|
-
t = verbose('decomposition -- Computing g(self) for an irreducible factor g of degree %s'%g.degree(), level=2)
|
|
5887
|
+
t = verbose('decomposition -- Computing g(self) for an irreducible factor g of degree %s' % g.degree(), level=2)
|
|
5819
5888
|
if is_diagonalizable:
|
|
5820
5889
|
B = g(self)
|
|
5821
5890
|
else:
|
|
5822
5891
|
B = g(self)
|
|
5823
|
-
t2 = verbose('decomposition -- raising g(self) to the power %s'%m,
|
|
5892
|
+
t2 = verbose('decomposition -- raising g(self) to the power %s' % m,
|
|
5893
|
+
level=2)
|
|
5824
5894
|
B = B ** m
|
|
5825
5895
|
verbose('done powering', level=2, t=t2)
|
|
5826
5896
|
t = verbose('decomposition -- done computing g(self)', level=2, t=t)
|
|
@@ -5911,7 +5981,7 @@ cdef class Matrix(Matrix1):
|
|
|
5911
5981
|
if not self.is_square():
|
|
5912
5982
|
raise ArithmeticError("self must be a square matrix")
|
|
5913
5983
|
if M.base_ring() != self.base_ring():
|
|
5914
|
-
raise ArithmeticError("base rings must be the same, but self is over %s and module is over %s"%(
|
|
5984
|
+
raise ArithmeticError("base rings must be the same, but self is over %s and module is over %s" % (
|
|
5915
5985
|
self.base_ring(), M.base_ring()))
|
|
5916
5986
|
if M.degree() != self.ncols():
|
|
5917
5987
|
raise ArithmeticError("M must be a subspace of an %s-dimensional space" % self.ncols())
|
|
@@ -5928,7 +5998,7 @@ cdef class Matrix(Matrix1):
|
|
|
5928
5998
|
sum_dim = sum([A.dimension() for A, _ in D])
|
|
5929
5999
|
assert sum_dim == M.dimension(), \
|
|
5930
6000
|
"bug in decomposition; " + \
|
|
5931
|
-
"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)
|
|
6001
|
+
"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)
|
|
5932
6002
|
|
|
5933
6003
|
# 3. Lift decomposition to subspaces of ambient vector space.
|
|
5934
6004
|
# Each basis vector for an element of D defines a linear
|
|
@@ -6475,12 +6545,22 @@ cdef class Matrix(Matrix1):
|
|
|
6475
6545
|
matrices with symbolic entries. ::
|
|
6476
6546
|
|
|
6477
6547
|
sage: A = matrix(QQ, 3, 3, range(9))
|
|
6478
|
-
sage: A.change_ring(RR).eigenspaces_left()
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
NotImplementedError: eigenspaces cannot be computed reliably
|
|
6482
|
-
for inexact rings such as Real Field with 53 bits of precision,
|
|
6548
|
+
sage: A.change_ring(RR).eigenspaces_left() # needs sage.rings.number_field
|
|
6549
|
+
doctest:warning...
|
|
6550
|
+
UserWarning: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision,
|
|
6483
6551
|
consult numerical or symbolic matrix classes for other options
|
|
6552
|
+
[(13.3484692283495,
|
|
6553
|
+
Vector space of degree 3 and dimension 0 over Real Field with 53 bits of precision
|
|
6554
|
+
User basis matrix:
|
|
6555
|
+
[]),
|
|
6556
|
+
(-0.000000000000000,
|
|
6557
|
+
Vector space of degree 3 and dimension 1 over Real Field with 53 bits of precision
|
|
6558
|
+
User basis matrix:
|
|
6559
|
+
[ 1.00000000000000 -2.00000000000000 1.00000000000000]),
|
|
6560
|
+
(-1.34846922834953,
|
|
6561
|
+
Vector space of degree 3 and dimension 0 over Real Field with 53 bits of precision
|
|
6562
|
+
User basis matrix:
|
|
6563
|
+
[])]
|
|
6484
6564
|
|
|
6485
6565
|
sage: # needs scipy
|
|
6486
6566
|
sage: em = A.change_ring(RDF).eigenmatrix_left()
|
|
@@ -6556,9 +6636,10 @@ cdef class Matrix(Matrix1):
|
|
|
6556
6636
|
msg = 'matrix must be square, not {0} x {1}'
|
|
6557
6637
|
raise TypeError(msg.format(self.nrows(), self.ncols()))
|
|
6558
6638
|
if not self.base_ring().is_exact():
|
|
6639
|
+
from warnings import warn
|
|
6559
6640
|
msg = ("eigenspaces cannot be computed reliably for inexact rings such as {0},\n",
|
|
6560
6641
|
"consult numerical or symbolic matrix classes for other options")
|
|
6561
|
-
|
|
6642
|
+
warn(''.join(msg).format(self.base_ring()))
|
|
6562
6643
|
|
|
6563
6644
|
format = self._eigenspace_format(format)
|
|
6564
6645
|
|
|
@@ -6830,13 +6911,21 @@ cdef class Matrix(Matrix1):
|
|
|
6830
6911
|
|
|
6831
6912
|
right_eigenspaces = eigenspaces_right
|
|
6832
6913
|
|
|
6833
|
-
def eigenvalues(self, extend=True):
|
|
6914
|
+
def eigenvalues(self, extend=True, algorithm=None) -> Sequence:
|
|
6834
6915
|
r"""
|
|
6835
6916
|
Return a sequence of the eigenvalues of a matrix, with
|
|
6836
6917
|
multiplicity. If the eigenvalues are roots of polynomials in ``QQ``,
|
|
6837
6918
|
then ``QQbar`` elements are returned that represent each separate
|
|
6838
6919
|
root.
|
|
6839
6920
|
|
|
6921
|
+
INPUT:
|
|
6922
|
+
|
|
6923
|
+
- ``extend`` -- (default: ``True``); see below
|
|
6924
|
+
- ``algorithm`` -- (default: ``None``); algorithm to use,
|
|
6925
|
+
supported values are ``'sage'``, ``'flint'``, ``'mpmath'``, ``'pari'``
|
|
6926
|
+
(passed to :meth:`eigenvectors_left`), or ``'pari_charpoly'``; if ``None``,
|
|
6927
|
+
the algorithm is chosen automatically
|
|
6928
|
+
|
|
6840
6929
|
If the option ``extend`` is set to ``False``, only eigenvalues in the base
|
|
6841
6930
|
ring are considered.
|
|
6842
6931
|
|
|
@@ -6927,6 +7016,96 @@ cdef class Matrix(Matrix1):
|
|
|
6927
7016
|
From: Finite Field in z3 of size 3^3
|
|
6928
7017
|
To: Algebraic closure of Finite Field of size 3
|
|
6929
7018
|
Defn: z3 |--> z3)
|
|
7019
|
+
|
|
7020
|
+
TESTS::
|
|
7021
|
+
|
|
7022
|
+
sage: import warnings
|
|
7023
|
+
sage: warnings.simplefilter("always")
|
|
7024
|
+
sage: m = matrix(RR, [[0, 1], [-2, 0]])
|
|
7025
|
+
|
|
7026
|
+
Test different algorithms::
|
|
7027
|
+
|
|
7028
|
+
sage: m.eigenvalues(algorithm="sage") # needs sage.libs.pari
|
|
7029
|
+
doctest:warning...
|
|
7030
|
+
UserWarning: Using generic algorithm for an inexact ring,
|
|
7031
|
+
which will probably give incorrect results due to numerical precision issues.
|
|
7032
|
+
[-1.41421356237310*I, 1.41421356237310*I]
|
|
7033
|
+
sage: m.eigenvalues(algorithm="flint") # needs sage.libs.flint
|
|
7034
|
+
doctest:warning...
|
|
7035
|
+
FutureWarning: This class/method/function is marked as experimental.
|
|
7036
|
+
It, its functionality or its interface might change without a formal deprecation.
|
|
7037
|
+
See https://github.com/sagemath/sage/issues/30393 for details.
|
|
7038
|
+
[-1.41421356237309*I, 1.41421356237310*I]
|
|
7039
|
+
sage: m.eigenvalues(algorithm="mpmath") # abs tol 1e-14
|
|
7040
|
+
[-1.41421356237309*I, 1.41421356237309*I]
|
|
7041
|
+
sage: m.eigenvalues(algorithm="pari") # abs tol 1e-14 # needs sage.libs.pari
|
|
7042
|
+
[-1.4142135623730950487637880730318329370*I,
|
|
7043
|
+
1.4142135623730950487637880730318329370*I]
|
|
7044
|
+
sage: m.eigenvalues(algorithm="pari_charpoly") # abs tol 1e-14 # needs sage.libs.pari
|
|
7045
|
+
[-1.41421356237309505*I, 1.41421356237309505*I]
|
|
7046
|
+
sage: m.eigenvalues()
|
|
7047
|
+
[-1.41421356237309505*I, 1.41421356237309505*I]
|
|
7048
|
+
sage: type(m.eigenvalues())
|
|
7049
|
+
<class 'sage.structure.sequence.Sequence_generic'>
|
|
7050
|
+
"""
|
|
7051
|
+
if algorithm is None:
|
|
7052
|
+
from sage.rings.abc import RealField, ComplexField
|
|
7053
|
+
R = self.base_ring()
|
|
7054
|
+
if isinstance(R, (RealField, ComplexField)):
|
|
7055
|
+
algorithm = "pari_charpoly"
|
|
7056
|
+
else:
|
|
7057
|
+
algorithm = "sage"
|
|
7058
|
+
if algorithm == "sage":
|
|
7059
|
+
return self._eigenvalues_sage(extend=extend)
|
|
7060
|
+
elif algorithm == "pari_charpoly":
|
|
7061
|
+
from sage.libs.pari import pari
|
|
7062
|
+
return Sequence(pari(self).charpoly().polroots().sage())
|
|
7063
|
+
else:
|
|
7064
|
+
return self._eigenvectors_result_to_eigenvalues(
|
|
7065
|
+
self._eigenvectors_left(
|
|
7066
|
+
extend=extend, algorithm=algorithm,
|
|
7067
|
+
suppress_future_warning=False))
|
|
7068
|
+
|
|
7069
|
+
def _eigenvectors_result_to_eigenvalues(self, eigenvectors: list) -> Sequence:
|
|
7070
|
+
"""
|
|
7071
|
+
Convert the result of :meth:`eigenvectors_left` to a sequence of eigenvalues
|
|
7072
|
+
suitable to be returned by :meth:`eigenvalues`.
|
|
7073
|
+
|
|
7074
|
+
INPUT:
|
|
7075
|
+
|
|
7076
|
+
- ``eigenvectors`` -- a list of tuples of the form ``(e,V,n)``
|
|
7077
|
+
as returned by :meth:`eigenvectors_left`
|
|
7078
|
+
|
|
7079
|
+
OUTPUT: a :class:`Sequence` of eigenvalues
|
|
7080
|
+
|
|
7081
|
+
TESTS::
|
|
7082
|
+
|
|
7083
|
+
sage: # needs sage.rings.number_field
|
|
7084
|
+
sage: A = matrix(QQ, [[1, 2], [3, 4]])
|
|
7085
|
+
sage: l = A.eigenvectors_left(); l
|
|
7086
|
+
[(-0.3722813232690144?, [(1, -0.4574271077563382?)], 1),
|
|
7087
|
+
(5.372281323269015?, [(1, 1.457427107756339?)], 1)]
|
|
7088
|
+
sage: A._eigenvectors_result_to_eigenvalues(l)
|
|
7089
|
+
[-0.3722813232690144?, 5.372281323269015?]
|
|
7090
|
+
"""
|
|
7091
|
+
return Sequence([e for e, _, _ in eigenvectors])
|
|
7092
|
+
|
|
7093
|
+
def _eigenvalues_sage(self, extend=True) -> Sequence:
|
|
7094
|
+
"""
|
|
7095
|
+
Compute the eigenvalues of a matrix using algorithm implemented in Sage.
|
|
7096
|
+
|
|
7097
|
+
INPUT:
|
|
7098
|
+
|
|
7099
|
+
- ``extend`` -- boolean (default: ``True``)
|
|
7100
|
+
|
|
7101
|
+
TESTS::
|
|
7102
|
+
|
|
7103
|
+
sage: # needs sage.rings.number_field
|
|
7104
|
+
sage: A = matrix(QQ, [[1, 2], [3, 4]])
|
|
7105
|
+
sage: A.eigenvalues(algorithm="sage") # indirect doctest
|
|
7106
|
+
[-0.3722813232690144?, 5.372281323269015?]
|
|
7107
|
+
sage: A._eigenvalues_sage()
|
|
7108
|
+
[-0.3722813232690144?, 5.372281323269015?]
|
|
6930
7109
|
"""
|
|
6931
7110
|
x = self.fetch('eigenvalues')
|
|
6932
7111
|
if x is not None:
|
|
@@ -6966,7 +7145,7 @@ cdef class Matrix(Matrix1):
|
|
|
6966
7145
|
self.cache('eigenvalues', eigenvalues)
|
|
6967
7146
|
return eigenvalues
|
|
6968
7147
|
|
|
6969
|
-
def eigenvectors_left(self, other=None, *, extend=True):
|
|
7148
|
+
def eigenvectors_left(self, other=None, *, extend=True, algorithm=None) -> list:
|
|
6970
7149
|
r"""
|
|
6971
7150
|
Compute the left eigenvectors of a matrix.
|
|
6972
7151
|
|
|
@@ -6979,14 +7158,25 @@ cdef class Matrix(Matrix1):
|
|
|
6979
7158
|
|
|
6980
7159
|
- ``extend`` -- boolean (default: ``True``)
|
|
6981
7160
|
|
|
7161
|
+
- ``algorithm`` -- string (default: ``None``); if ``None``, then it is
|
|
7162
|
+
chosen automatically; options are:
|
|
7163
|
+
|
|
7164
|
+
* ``'sage'``
|
|
7165
|
+
* ``'flint'``
|
|
7166
|
+
* ``'mpmath'``
|
|
7167
|
+
* ``'pari'``
|
|
7168
|
+
* ``'scipy'`` - only supported for matrices over :class:`RDF <sage.rings.real_double.RealDoubleField_class>`
|
|
7169
|
+
and :class:`CDF <sage.rings.complex_double.ComplexDoubleField_class>`
|
|
7170
|
+
|
|
6982
7171
|
OUTPUT:
|
|
6983
7172
|
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
7173
|
+
Returns a list of tuples of the form ``(e,V,n)``,
|
|
7174
|
+
each tuple corresponds to a distinct eigenvalue,
|
|
7175
|
+
where ``e`` is the eigenvalue, ``V`` is a list of eigenvectors forming a
|
|
7176
|
+
basis for the corresponding left eigenspace, and ``n`` is the algebraic
|
|
6987
7177
|
multiplicity of the eigenvalue.
|
|
6988
7178
|
|
|
6989
|
-
If the option extend is set to False
|
|
7179
|
+
If the option ``extend`` is set to ``False``, then only the eigenvalues that
|
|
6990
7180
|
live in the base ring are considered.
|
|
6991
7181
|
|
|
6992
7182
|
EXAMPLES:
|
|
@@ -7042,6 +7232,22 @@ cdef class Matrix(Matrix1):
|
|
|
7042
7232
|
sage: K.<i> = QuadraticField(-1)
|
|
7043
7233
|
sage: m = matrix(K, 4, [2,4*i,-i,0, -4*i,2,-1,0, 2*i,-2,0,0, 4*i+4, 4*i-4,1-i,-2])
|
|
7044
7234
|
sage: assert all(m*v == e*v for e, vs, _ in m.eigenvectors_right() for v in vs)
|
|
7235
|
+
|
|
7236
|
+
The following currently uses ``algorithm="flint"`` under the hood,
|
|
7237
|
+
but ``FutureWarning`` must not be raised. This is because the internal
|
|
7238
|
+
implementation may change in the future to keep the external interface.
|
|
7239
|
+
|
|
7240
|
+
::
|
|
7241
|
+
|
|
7242
|
+
sage: # needs sage.libs.flint
|
|
7243
|
+
sage: import warnings
|
|
7244
|
+
sage: warnings.simplefilter("always")
|
|
7245
|
+
sage: m = matrix(RR, [[0, 1], [-2, 0]])
|
|
7246
|
+
sage: m.eigenvectors_left()
|
|
7247
|
+
[(-1.41421356237309*I, [(-0.816496580927726, -0.577350269189626*I)], 1),
|
|
7248
|
+
(1.41421356237310*I, [(-0.866025403784438*I, -0.612372435695794)], 1)]
|
|
7249
|
+
sage: m.eigenvectors_left(extend=False)
|
|
7250
|
+
[]
|
|
7045
7251
|
"""
|
|
7046
7252
|
if other is not None:
|
|
7047
7253
|
if isinstance(other, bool):
|
|
@@ -7057,15 +7263,77 @@ cdef class Matrix(Matrix1):
|
|
|
7057
7263
|
'for RDF and CDF, but not for %s'
|
|
7058
7264
|
% self.base_ring())
|
|
7059
7265
|
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7266
|
+
if algorithm is None:
|
|
7267
|
+
R = self.base_ring()
|
|
7268
|
+
from sage.rings.abc import RealField, ComplexField
|
|
7269
|
+
if isinstance(R, (RealField, ComplexField)):
|
|
7270
|
+
return self._eigenvectors_left(
|
|
7271
|
+
other, extend=extend, algorithm='flint', suppress_future_warning=True)
|
|
7272
|
+
else:
|
|
7273
|
+
algorithm = 'sage'
|
|
7274
|
+
return self._eigenvectors_left(
|
|
7275
|
+
other, extend=extend, algorithm=algorithm, suppress_future_warning=False)
|
|
7276
|
+
|
|
7277
|
+
def _eigenvectors_left(self, other=None, *, extend: bool, algorithm: str,
|
|
7278
|
+
suppress_future_warning: bool) -> list:
|
|
7279
|
+
"""
|
|
7280
|
+
Do the same thing as :meth:`eigenvectors_left`, but ``algorithm``
|
|
7281
|
+
cannot be ``None``, and ``suppress_future_warning`` is provided
|
|
7282
|
+
to suppress the ``FutureWarning`` raised by the flint method.
|
|
7063
7283
|
|
|
7284
|
+
TESTS::
|
|
7285
|
+
|
|
7286
|
+
sage: # needs sage.libs.flint
|
|
7287
|
+
sage: m = matrix(RR, [[0, 1], [-2, 0]])
|
|
7288
|
+
sage: m._eigenvectors_left(extend=False, algorithm="flint", suppress_future_warning=True)
|
|
7289
|
+
[]
|
|
7290
|
+
"""
|
|
7291
|
+
if algorithm == 'sage':
|
|
7292
|
+
return self._eigenvectors_left_sage(extend=extend)
|
|
7293
|
+
elif algorithm == 'flint':
|
|
7294
|
+
return self._fix_eigenvectors_extend(self._eigenvectors_left_flint(suppress_future_warning), extend)
|
|
7295
|
+
elif algorithm == 'mpmath':
|
|
7296
|
+
return self._fix_eigenvectors_extend(self._eigenvectors_left_mpmath(), extend)
|
|
7297
|
+
elif algorithm == 'pari':
|
|
7298
|
+
return self._fix_eigenvectors_extend(self._eigenvectors_left_pari(), extend)
|
|
7299
|
+
else:
|
|
7300
|
+
raise ValueError('algorithm value not recognized')
|
|
7301
|
+
|
|
7302
|
+
def _eigenvectors_left_sage(self, *, extend=True) -> list:
|
|
7303
|
+
"""
|
|
7304
|
+
Compute the left eigenvectors of a matrix
|
|
7305
|
+
using a generic algorithm implemented in Sage.
|
|
7306
|
+
|
|
7307
|
+
INPUT:
|
|
7308
|
+
|
|
7309
|
+
- ``extend`` -- boolean (default: ``True``)
|
|
7310
|
+
|
|
7311
|
+
OUTPUT:
|
|
7312
|
+
|
|
7313
|
+
See :meth:`eigenvectors_left`.
|
|
7314
|
+
|
|
7315
|
+
TESTS::
|
|
7316
|
+
|
|
7317
|
+
sage: # needs sage.rings.number_field
|
|
7318
|
+
sage: import warnings
|
|
7319
|
+
sage: warnings.simplefilter("always")
|
|
7320
|
+
sage: m = matrix(RR, [[0, 1], [-2, 0]])
|
|
7321
|
+
sage: m.eigenvectors_left(algorithm="sage")
|
|
7322
|
+
doctest:warning...
|
|
7323
|
+
UserWarning: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision,
|
|
7324
|
+
consult numerical or symbolic matrix classes for other options
|
|
7325
|
+
[(-1.41421356237310*I, [(1.00000000000000, 0.707106781186548*I)], 1),
|
|
7326
|
+
(1.41421356237310*I, [(1.00000000000000, -0.707106781186548*I)], 1)]
|
|
7327
|
+
sage: m.eigenvectors_left(algorithm="sage", extend=False)
|
|
7328
|
+
doctest:warning...
|
|
7329
|
+
UserWarning: eigenspaces cannot be computed reliably for inexact rings such as Real Field with 53 bits of precision,
|
|
7330
|
+
consult numerical or symbolic matrix classes for other options
|
|
7331
|
+
[]
|
|
7332
|
+
"""
|
|
7064
7333
|
if not self.base_ring().is_exact():
|
|
7065
7334
|
from warnings import warn
|
|
7066
7335
|
warn("Using generic algorithm for an inexact ring, which may result in garbage from numerical precision issues.")
|
|
7067
7336
|
|
|
7068
|
-
from sage.categories.homset import hom
|
|
7069
7337
|
eigenspaces = self.eigenspaces_left(format='galois', algebraic_multiplicity=True)
|
|
7070
7338
|
evec_list = []
|
|
7071
7339
|
n = self._nrows
|
|
@@ -7079,20 +7347,169 @@ cdef class Matrix(Matrix1):
|
|
|
7079
7347
|
if eigval.parent().fraction_field() == F:
|
|
7080
7348
|
evec_eval_list.append((eigval, eigbasis, eigmult))
|
|
7081
7349
|
else:
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7350
|
+
from sage.categories.homset import Hom
|
|
7351
|
+
from sage.rings.abc import RealField
|
|
7352
|
+
if isinstance(self.base_ring(), RealField):
|
|
7353
|
+
# then eigval is an element of RR[x]/f(x)
|
|
7354
|
+
# find all morphism of that ring into CC
|
|
7355
|
+
f = eigval.parent().modulus()
|
|
7356
|
+
rs = f.roots(self.base_ring().complex_field(), multiplicities=False)
|
|
7357
|
+
g = eigval.lift()
|
|
7358
|
+
eigval_conj = [g(r) for r in rs]
|
|
7359
|
+
else:
|
|
7360
|
+
try:
|
|
7361
|
+
from sage.rings.qqbar import QQbar
|
|
7362
|
+
eigval_conj = eigval.galois_conjugates(QQbar)
|
|
7363
|
+
except AttributeError:
|
|
7364
|
+
raise NotImplementedError("eigenvectors are not implemented for matrices with eigenvalues that are not in the fraction field of the base ring or in QQbar")
|
|
7087
7365
|
|
|
7088
7366
|
for e in eigval_conj:
|
|
7089
|
-
m =
|
|
7367
|
+
m = Hom(eigval.parent(), e.parent())(e, check=False)
|
|
7368
|
+
# check=False because the base_ring may not be exact
|
|
7090
7369
|
space = (e.parent())**n
|
|
7091
7370
|
evec_list = [(space)([m(i) for i in v]) for v in eigbasis]
|
|
7092
7371
|
evec_eval_list.append((e, evec_list, eigmult))
|
|
7093
7372
|
|
|
7094
7373
|
return evec_eval_list
|
|
7095
7374
|
|
|
7375
|
+
def _fix_eigenvectors_extend(self, eigenvectors: list, extend: bool) -> list:
|
|
7376
|
+
"""
|
|
7377
|
+
Fix the eigenvectors if the extend option is set to ``False``.
|
|
7378
|
+
|
|
7379
|
+
INPUT:
|
|
7380
|
+
|
|
7381
|
+
- ``eigenvectors`` -- a list of tuples of the form ``(e,V,n)``
|
|
7382
|
+
as returned by :meth:`eigenvectors_left`
|
|
7383
|
+
- ``extend`` -- boolean
|
|
7384
|
+
|
|
7385
|
+
OUTPUT:
|
|
7386
|
+
|
|
7387
|
+
If ``extend`` is ``True``, return ``eigenvectors`` unchanged.
|
|
7388
|
+
Otherwise, return a new list with only the eigenvalues that live in the base ring.
|
|
7389
|
+
|
|
7390
|
+
TESTS::
|
|
7391
|
+
|
|
7392
|
+
sage: m = matrix(RR, [[0, 1], [-2, 0]])
|
|
7393
|
+
sage: l = m.eigenvectors_left(algorithm="pari"); l # abs tol 1e-14 # needs sage.libs.pari
|
|
7394
|
+
[(-1.4142135623730950487637880730318329370*I,
|
|
7395
|
+
[(0.707106781186547524*I, 1.00000000000000000)],
|
|
7396
|
+
1),
|
|
7397
|
+
(1.4142135623730950487637880730318329370*I,
|
|
7398
|
+
[(-0.707106781186547524*I, 1.00000000000000000)],
|
|
7399
|
+
1)]
|
|
7400
|
+
sage: m._fix_eigenvectors_extend(l, extend=True) # abs tol 1e-14 # needs sage.libs.pari
|
|
7401
|
+
[(-1.4142135623730950487637880730318329370*I,
|
|
7402
|
+
[(0.707106781186547524*I, 1.00000000000000000)],
|
|
7403
|
+
1),
|
|
7404
|
+
(1.4142135623730950487637880730318329370*I,
|
|
7405
|
+
[(-0.707106781186547524*I, 1.00000000000000000)],
|
|
7406
|
+
1)]
|
|
7407
|
+
sage: m._fix_eigenvectors_extend(l, extend=False) # needs sage.libs.pari
|
|
7408
|
+
[]
|
|
7409
|
+
"""
|
|
7410
|
+
if extend:
|
|
7411
|
+
return eigenvectors
|
|
7412
|
+
R = self.base_ring()
|
|
7413
|
+
try:
|
|
7414
|
+
if R.algebraic_closure() is R:
|
|
7415
|
+
return eigenvectors
|
|
7416
|
+
except (AttributeError, NotImplementedError):
|
|
7417
|
+
pass
|
|
7418
|
+
return [(e, V, n) for e, V, n in eigenvectors if e in R]
|
|
7419
|
+
|
|
7420
|
+
def _eigenvectors_left_flint(self, suppress_future_warning: bool) -> list:
|
|
7421
|
+
"""
|
|
7422
|
+
Compute the left eigenvectors of a matrix
|
|
7423
|
+
using the FLINT library.
|
|
7424
|
+
|
|
7425
|
+
Only works for matrices over ``RealField`` or ``ComplexField``.
|
|
7426
|
+
|
|
7427
|
+
INPUT:
|
|
7428
|
+
|
|
7429
|
+
- ``suppress_future_warning`` -- boolean; whether to suppress
|
|
7430
|
+
the ``FutureWarning``
|
|
7431
|
+
|
|
7432
|
+
OUTPUT:
|
|
7433
|
+
|
|
7434
|
+
See :meth:`eigenvectors_left`.
|
|
7435
|
+
|
|
7436
|
+
TESTS:
|
|
7437
|
+
|
|
7438
|
+
This method is supposed to raise a ``FutureWarning`` but
|
|
7439
|
+
the implementation in :class:`sage.misc.superseded.experimental`
|
|
7440
|
+
only raises the warning at most once, because of doctest ordering
|
|
7441
|
+
the warning is not seen below. See :issue:`39811`. ::
|
|
7442
|
+
|
|
7443
|
+
sage: # needs sage.libs.flint
|
|
7444
|
+
sage: m = matrix(RR, [[0, 1], [-2, 0]])
|
|
7445
|
+
sage: m.eigenvectors_left(algorithm="flint") # indirect doctest
|
|
7446
|
+
[(-1.41421356237309*I, [(-0.816496580927726, -0.577350269189626*I)], 1),
|
|
7447
|
+
(1.41421356237310*I, [(-0.866025403784438*I, -0.612372435695794)], 1)]
|
|
7448
|
+
sage: m.eigenvectors_left(algorithm="flint", extend=False)
|
|
7449
|
+
[]
|
|
7450
|
+
"""
|
|
7451
|
+
if suppress_future_warning:
|
|
7452
|
+
import warnings
|
|
7453
|
+
with warnings.catch_warnings():
|
|
7454
|
+
warnings.simplefilter("ignore", category=FutureWarning)
|
|
7455
|
+
result = self._eigenvectors_left_flint(False)
|
|
7456
|
+
return result
|
|
7457
|
+
from sage.rings.complex_arb import ComplexBallField
|
|
7458
|
+
from sage.rings.complex_mpfr import ComplexField
|
|
7459
|
+
C = ComplexField(self.base_ring().precision())
|
|
7460
|
+
return [(C(e), [v.change_ring(C) for v in V], n) for e, V, n in
|
|
7461
|
+
self.change_ring(ComplexBallField(self.base_ring().precision())).eigenvectors_left()]
|
|
7462
|
+
|
|
7463
|
+
def _eigenvectors_left_mpmath(self) -> list:
|
|
7464
|
+
"""
|
|
7465
|
+
Compute the left eigenvectors of a matrix
|
|
7466
|
+
using ``mpmath``.
|
|
7467
|
+
|
|
7468
|
+
Only works for matrices over ``RealField`` or ``ComplexField``.
|
|
7469
|
+
|
|
7470
|
+
sage: m = matrix(RR, [[0, 1], [-2, 0]])
|
|
7471
|
+
sage: m.eigenvectors_left(algorithm="mpmath")
|
|
7472
|
+
[(-1.41421356237309*I, [(-0.866025403784439, -0.612372435695794*I)], 1),
|
|
7473
|
+
(1.41421356237309*I, [(-0.816496580927726*I, -0.577350269189626)], 1)]
|
|
7474
|
+
sage: m.eigenvectors_left(algorithm="mpmath", extend=False)
|
|
7475
|
+
[]
|
|
7476
|
+
"""
|
|
7477
|
+
from mpmath import mp
|
|
7478
|
+
eigenvalues, eigenvectors = mp.eig(self._mpmath_(), left=True, right=False)
|
|
7479
|
+
from sage.rings.complex_mpfr import ComplexField
|
|
7480
|
+
C = ComplexField(self.base_ring().precision())
|
|
7481
|
+
from sage.modules.free_module_element import vector
|
|
7482
|
+
return [
|
|
7483
|
+
(C(e), [vector(C, V)], 1)
|
|
7484
|
+
for e, V in zip(eigenvalues, eigenvectors.tolist())
|
|
7485
|
+
]
|
|
7486
|
+
|
|
7487
|
+
def _eigenvectors_left_pari(self) -> list:
|
|
7488
|
+
"""
|
|
7489
|
+
Compute the left eigenvectors of a matrix
|
|
7490
|
+
using the PARI library.
|
|
7491
|
+
|
|
7492
|
+
Only works for matrices over ``RealField`` or ``ComplexField``.
|
|
7493
|
+
|
|
7494
|
+
sage: # needs sage.libs.pari
|
|
7495
|
+
sage: m = matrix(RR, [[0, 1], [-2, 0]])
|
|
7496
|
+
sage: m.eigenvectors_left(algorithm="pari") # abs tol 1e-14
|
|
7497
|
+
[(-1.4142135623730950487637880730318329370*I,
|
|
7498
|
+
[(0.707106781186547524*I, 1.00000000000000000)],
|
|
7499
|
+
1),
|
|
7500
|
+
(1.4142135623730950487637880730318329370*I,
|
|
7501
|
+
[(-0.707106781186547524*I, 1.00000000000000000)],
|
|
7502
|
+
1)]
|
|
7503
|
+
sage: m.eigenvectors_left(algorithm="pari", extend=False)
|
|
7504
|
+
[]
|
|
7505
|
+
"""
|
|
7506
|
+
from sage.libs.pari import pari
|
|
7507
|
+
eigenvalues, eigenvectors = pari(self).mateigen(flag=1, precision=self.base_ring().precision()).sage()
|
|
7508
|
+
return [
|
|
7509
|
+
(e, [V], 1)
|
|
7510
|
+
for e, V in zip(eigenvalues, eigenvectors.columns())
|
|
7511
|
+
]
|
|
7512
|
+
|
|
7096
7513
|
left_eigenvectors = eigenvectors_left
|
|
7097
7514
|
|
|
7098
7515
|
def eigenvectors_right(self, other=None, *, extend=True):
|
|
@@ -7780,7 +8197,7 @@ cdef class Matrix(Matrix1):
|
|
|
7780
8197
|
try:
|
|
7781
8198
|
a, d, p = self._echelon_form_PID()
|
|
7782
8199
|
except TypeError as msg:
|
|
7783
|
-
raise NotImplementedError("%s\nechelon form over %s not yet implemented"%(msg, self.base_ring()))
|
|
8200
|
+
raise NotImplementedError("%s\nechelon form over %s not yet implemented" % (msg, self.base_ring()))
|
|
7784
8201
|
|
|
7785
8202
|
for c from 0 <= c < self.ncols():
|
|
7786
8203
|
for r from 0 <= r < self.nrows():
|
|
@@ -7984,7 +8401,7 @@ cdef class Matrix(Matrix1):
|
|
|
7984
8401
|
kwds['algorithm'] = algorithm
|
|
7985
8402
|
return self._echelonize_ring(**kwds)
|
|
7986
8403
|
except ArithmeticError as msg:
|
|
7987
|
-
raise NotImplementedError("%s\nEchelon form not implemented over '%s'."%(msg, basring))
|
|
8404
|
+
raise NotImplementedError("%s\nEchelon form not implemented over '%s'." % (msg, basring))
|
|
7988
8405
|
|
|
7989
8406
|
def echelon_form(self, algorithm='default', cutoff=0, **kwds):
|
|
7990
8407
|
r"""
|
|
@@ -8970,7 +9387,8 @@ cdef class Matrix(Matrix1):
|
|
|
8970
9387
|
[ 0 0 0 0]
|
|
8971
9388
|
[ 0 0 0 0]
|
|
8972
9389
|
"""
|
|
8973
|
-
tm = verbose('strassen echelon of %s x %s matrix'%(self._nrows, self._ncols),
|
|
9390
|
+
tm = verbose('strassen echelon of %s x %s matrix' % (self._nrows, self._ncols),
|
|
9391
|
+
level=2)
|
|
8974
9392
|
|
|
8975
9393
|
self.check_mutability()
|
|
8976
9394
|
|
|
@@ -9248,7 +9666,7 @@ cdef class Matrix(Matrix1):
|
|
|
9248
9666
|
"""
|
|
9249
9667
|
if self._subdivisions is None:
|
|
9250
9668
|
self._subdivisions = ([0, self._nrows], [0, self._ncols])
|
|
9251
|
-
key = "subdivision %s %s"%(i, j)
|
|
9669
|
+
key = "subdivision %s %s" % (i, j)
|
|
9252
9670
|
sd = self.fetch(key)
|
|
9253
9671
|
if sd is None:
|
|
9254
9672
|
sd = self[self._subdivisions[0][i]:self._subdivisions[0][i+1],
|
|
@@ -9296,10 +9714,10 @@ cdef class Matrix(Matrix1):
|
|
|
9296
9714
|
if not i and not j:
|
|
9297
9715
|
return self[x, y]
|
|
9298
9716
|
else:
|
|
9299
|
-
raise IndexError("No such submatrix %s, %s"%(i, j))
|
|
9717
|
+
raise IndexError("No such submatrix %s, %s" % (i, j))
|
|
9300
9718
|
if x >= self._subdivisions[0][i+1]-self._subdivisions[0][i] or \
|
|
9301
9719
|
y >= self._subdivisions[1][j+1]-self._subdivisions[1][j]:
|
|
9302
|
-
raise IndexError("Submatrix %s,%s has no entry %s,%s"%(i, j, x, y))
|
|
9720
|
+
raise IndexError("Submatrix %s,%s has no entry %s,%s" % (i, j, x, y))
|
|
9303
9721
|
return self[self._subdivisions[0][i] + x, self._subdivisions[1][j] + y]
|
|
9304
9722
|
|
|
9305
9723
|
def _subdivide_on_augment(self, left, right):
|
|
@@ -10246,7 +10664,7 @@ cdef class Matrix(Matrix1):
|
|
|
10246
10664
|
sage: a.density()
|
|
10247
10665
|
0
|
|
10248
10666
|
"""
|
|
10249
|
-
cdef
|
|
10667
|
+
cdef Py_ssize_t x, y, k
|
|
10250
10668
|
k = 0
|
|
10251
10669
|
nr = self.nrows()
|
|
10252
10670
|
nc = self.ncols()
|
|
@@ -10478,7 +10896,7 @@ cdef class Matrix(Matrix1):
|
|
|
10478
10896
|
raise ValueError("self must be a square matrix")
|
|
10479
10897
|
|
|
10480
10898
|
A = self.charpoly().shift(-1)(self)
|
|
10481
|
-
return A if n%2 else -A
|
|
10899
|
+
return A if n % 2 else -A
|
|
10482
10900
|
|
|
10483
10901
|
def QR(self, full=True):
|
|
10484
10902
|
r"""
|
|
@@ -12955,7 +13373,188 @@ cdef class Matrix(Matrix1):
|
|
|
12955
13373
|
else:
|
|
12956
13374
|
return subspace
|
|
12957
13375
|
|
|
12958
|
-
def
|
|
13376
|
+
def _cholesky_extended_ff(self):
|
|
13377
|
+
r"""
|
|
13378
|
+
Performs the extended Cholesky decomposition of a Hermitian matrix over a finite field of square order.
|
|
13379
|
+
|
|
13380
|
+
INPUT:
|
|
13381
|
+
|
|
13382
|
+
- ``self`` -- a square matrix with entries from a finite field of square order
|
|
13383
|
+
|
|
13384
|
+
.. SEEALSO::
|
|
13385
|
+
|
|
13386
|
+
:meth:`cholesky()`
|
|
13387
|
+
|
|
13388
|
+
OUTPUT:
|
|
13389
|
+
|
|
13390
|
+
For a Hermitian matrix `A` the routine returns a matrix `B` such that,
|
|
13391
|
+
|
|
13392
|
+
.. MATH::
|
|
13393
|
+
|
|
13394
|
+
A = B B^*,
|
|
13395
|
+
|
|
13396
|
+
where `B^*` is the conjugate-transpose.
|
|
13397
|
+
|
|
13398
|
+
ALGORITHM:
|
|
13399
|
+
|
|
13400
|
+
First, we ensure the matrix is square and defined over a finite field of square order. Then we can perform the conjugate-symmetric
|
|
13401
|
+
version of Gaussian elimination, but the resulting decomposition matrix `L` might not be lower triangular.
|
|
13402
|
+
|
|
13403
|
+
This is a translation of ``BaseChangeToCanonical`` from the GAP ``forms`` package (for a Hermitian form).
|
|
13404
|
+
|
|
13405
|
+
EXAMPLES:
|
|
13406
|
+
|
|
13407
|
+
Here we use the extended decomposition, where the result may not be a lower triangular matrix::
|
|
13408
|
+
|
|
13409
|
+
sage: # needs sage.rings.finite_rings
|
|
13410
|
+
sage: U = matrix(GF(17**2),[[0,1],[1,0]])
|
|
13411
|
+
sage: B = U._cholesky_extended_ff(); B
|
|
13412
|
+
[13*z2 + 6 3*z2 + 16]
|
|
13413
|
+
[13*z2 + 6 14*z2 + 1]
|
|
13414
|
+
sage: U == B * B.H
|
|
13415
|
+
True
|
|
13416
|
+
sage: U = matrix(GF(13**2),[[1,4,7],[4,1,4],[7,4,1]])
|
|
13417
|
+
sage: B = U._cholesky_extended_ff(); B
|
|
13418
|
+
[ 1 0 0]
|
|
13419
|
+
[ 4 7*z2 + 3 0]
|
|
13420
|
+
[ 7 6*z2 + 10 12*z2 + 6]
|
|
13421
|
+
sage: U == B * B.H
|
|
13422
|
+
True
|
|
13423
|
+
sage: U = matrix(GF(7**2), [[0, 1, 2], [1, 0, 1], [2, 1, 0]])
|
|
13424
|
+
sage: B = U._cholesky_extended_ff(); B
|
|
13425
|
+
[4*z2 + 2 6*z2 0]
|
|
13426
|
+
[4*z2 + 2 z2 0]
|
|
13427
|
+
[5*z2 + 6 z2 z2]
|
|
13428
|
+
sage: U == B * B.H
|
|
13429
|
+
True
|
|
13430
|
+
|
|
13431
|
+
TESTS:
|
|
13432
|
+
|
|
13433
|
+
If the matrix is not full rank, we compute the rank and throw an exception.
|
|
13434
|
+
|
|
13435
|
+
sage: # needs sage.rings.finite_rings
|
|
13436
|
+
sage: U = matrix(GF(3**2),[[1,4,7],[4,1,4],[7,4,1]])
|
|
13437
|
+
sage: U._cholesky_extended_ff()
|
|
13438
|
+
Traceback (most recent call last):
|
|
13439
|
+
...
|
|
13440
|
+
ValueError: matrix is not full rank
|
|
13441
|
+
sage: U = matrix(GF(3**2),[[0,4,7],[4,1,4],[7,4,1]])
|
|
13442
|
+
sage: U._cholesky_extended_ff()
|
|
13443
|
+
Traceback (most recent call last):
|
|
13444
|
+
...
|
|
13445
|
+
ValueError: matrix is not full rank
|
|
13446
|
+
"""
|
|
13447
|
+
from sage.matrix.constructor import identity_matrix
|
|
13448
|
+
|
|
13449
|
+
if not self.is_hermitian():
|
|
13450
|
+
raise ValueError("matrix is not Hermitian")
|
|
13451
|
+
|
|
13452
|
+
F = self._base_ring
|
|
13453
|
+
n = self.nrows()
|
|
13454
|
+
if self.fetch("rank") not in [n, None]:
|
|
13455
|
+
raise ValueError("matrix is not full rank")
|
|
13456
|
+
if not (F.is_finite() and F.order().is_square()):
|
|
13457
|
+
raise ValueError("the base ring must be a finite field of square order")
|
|
13458
|
+
|
|
13459
|
+
q = F.order().sqrt(extend=False)
|
|
13460
|
+
|
|
13461
|
+
def conj_square_root(u):
|
|
13462
|
+
if u == 0:
|
|
13463
|
+
return 0
|
|
13464
|
+
z = F.multiplicative_generator()
|
|
13465
|
+
k = u.log(z)
|
|
13466
|
+
if k % (q + 1) != 0:
|
|
13467
|
+
raise ValueError(f"unable to factor: {u} is not in base field GF({q})")
|
|
13468
|
+
return z ** (k//(q+1))
|
|
13469
|
+
|
|
13470
|
+
if self.nrows() == 1 and self.ncols() == 1:
|
|
13471
|
+
return self.__class__(F, [conj_square_root(self[0][0])])
|
|
13472
|
+
|
|
13473
|
+
A = copy(self)
|
|
13474
|
+
D = identity_matrix(F, n)
|
|
13475
|
+
row = -1
|
|
13476
|
+
|
|
13477
|
+
# Diagonalize A
|
|
13478
|
+
while row != n - 1:
|
|
13479
|
+
row += 1
|
|
13480
|
+
|
|
13481
|
+
# Look for a non-zero element on the main diagonal, starting from `row`
|
|
13482
|
+
i = row
|
|
13483
|
+
while i < n and A[i, i].is_zero():
|
|
13484
|
+
i += 1
|
|
13485
|
+
|
|
13486
|
+
if i == row:
|
|
13487
|
+
# Do nothing since A[row, row] != 0
|
|
13488
|
+
pass
|
|
13489
|
+
elif i < n:
|
|
13490
|
+
# Swap to ensure A[row, row] != 0
|
|
13491
|
+
A.swap_rows(row, i)
|
|
13492
|
+
A.swap_columns(row, i)
|
|
13493
|
+
D.swap_rows(row, i)
|
|
13494
|
+
else:
|
|
13495
|
+
# All entries on the main diagonal are zero; look for an off-diagonal element
|
|
13496
|
+
i = row
|
|
13497
|
+
while i < n - 1:
|
|
13498
|
+
k = i + 1
|
|
13499
|
+
while k < n and A[i, k].is_zero():
|
|
13500
|
+
k += 1
|
|
13501
|
+
if k == n:
|
|
13502
|
+
i += 1
|
|
13503
|
+
else:
|
|
13504
|
+
break
|
|
13505
|
+
|
|
13506
|
+
if i == n - 1:
|
|
13507
|
+
# All elements are zero; terminate
|
|
13508
|
+
row -= 1
|
|
13509
|
+
r = row + 1
|
|
13510
|
+
break
|
|
13511
|
+
|
|
13512
|
+
# Fetch the non-zero element and place it at A[row, row + 1]
|
|
13513
|
+
if i != row:
|
|
13514
|
+
A.swap_rows(row, i)
|
|
13515
|
+
A.swap_columns(row, i)
|
|
13516
|
+
D.swap_rows(row, i)
|
|
13517
|
+
|
|
13518
|
+
A.swap_rows(row + 1, k)
|
|
13519
|
+
A.swap_columns(row + 1, k)
|
|
13520
|
+
D.swap_rows(row + 1, k)
|
|
13521
|
+
|
|
13522
|
+
b = ~A[row + 1, row]
|
|
13523
|
+
A.add_multiple_of_column(row, row + 1, b**q)
|
|
13524
|
+
A.add_multiple_of_row(row, row + 1, b)
|
|
13525
|
+
D.add_multiple_of_row(row, row + 1, b)
|
|
13526
|
+
|
|
13527
|
+
# Eliminate below-diagonal entries in the current column
|
|
13528
|
+
a = ~(-A[row, row])
|
|
13529
|
+
for i in range(row + 1, n):
|
|
13530
|
+
b = A[i, row] * a
|
|
13531
|
+
if not b.is_zero():
|
|
13532
|
+
A.add_multiple_of_column(i, row, b**q)
|
|
13533
|
+
A.add_multiple_of_row(i, row, b)
|
|
13534
|
+
D.add_multiple_of_row(i, row, b)
|
|
13535
|
+
|
|
13536
|
+
# Count how many variables have been used
|
|
13537
|
+
if row == n - 1:
|
|
13538
|
+
if A[n - 1, n - 1]: # nonzero entry
|
|
13539
|
+
r = n
|
|
13540
|
+
else:
|
|
13541
|
+
r = n - 1
|
|
13542
|
+
|
|
13543
|
+
if r < n:
|
|
13544
|
+
self.cache('rank', r)
|
|
13545
|
+
raise ValueError("matrix is not full rank")
|
|
13546
|
+
|
|
13547
|
+
# Normalize diagonal elements to 1
|
|
13548
|
+
for i in range(r):
|
|
13549
|
+
a = A[i, i]
|
|
13550
|
+
if not a.is_one():
|
|
13551
|
+
# Find an element `b` such that `a = b*b^q = b^(q+1)`
|
|
13552
|
+
b = conj_square_root(a)
|
|
13553
|
+
D.rescale_row(i, 1 / b)
|
|
13554
|
+
|
|
13555
|
+
return D.inverse()
|
|
13556
|
+
|
|
13557
|
+
def cholesky(self, extended=False):
|
|
12959
13558
|
r"""
|
|
12960
13559
|
Return the Cholesky decomposition of a Hermitian matrix.
|
|
12961
13560
|
|
|
@@ -13001,6 +13600,15 @@ cdef class Matrix(Matrix1):
|
|
|
13001
13600
|
closure or the algebraic reals, depending on whether or not
|
|
13002
13601
|
imaginary numbers are required.
|
|
13003
13602
|
|
|
13603
|
+
Over finite fields, the Cholesky decomposition might
|
|
13604
|
+
not exist, but when the field has square order (i.e.,
|
|
13605
|
+
`\GF{q^2}`), then we can perform the conjugate-symmetric
|
|
13606
|
+
version of Gaussian elimination, but the resulting
|
|
13607
|
+
decomposition matrix `L` might not be lower triangular.
|
|
13608
|
+
|
|
13609
|
+
This is a translation of ``BaseChangeToCanonical`` from
|
|
13610
|
+
the GAP ``forms`` package (for a Hermitian form).
|
|
13611
|
+
|
|
13004
13612
|
EXAMPLES:
|
|
13005
13613
|
|
|
13006
13614
|
This simple example has a result with entries that remain
|
|
@@ -13171,6 +13779,31 @@ cdef class Matrix(Matrix1):
|
|
|
13171
13779
|
...
|
|
13172
13780
|
ValueError: matrix is not positive definite
|
|
13173
13781
|
|
|
13782
|
+
Here we use the extended decomposition, where the result
|
|
13783
|
+
may not be a lower triangular matrix::
|
|
13784
|
+
|
|
13785
|
+
sage: # needs sage.rings.finite_rings
|
|
13786
|
+
sage: U = matrix(GF(5**2),[[0,1],[1,0]])
|
|
13787
|
+
sage: B = U.cholesky(extended=True); B
|
|
13788
|
+
[3*z2 4*z2]
|
|
13789
|
+
[3*z2 z2]
|
|
13790
|
+
sage: U == B * B.H
|
|
13791
|
+
True
|
|
13792
|
+
sage: U = matrix(GF(11**2),[[1,4,7],[4,1,4],[7,4,1]])
|
|
13793
|
+
sage: B = U.cholesky(extended=True); B
|
|
13794
|
+
[ 1 0 0]
|
|
13795
|
+
[ 4 9*z2 + 2 0]
|
|
13796
|
+
[ 7 10*z2 + 1 3*z2 + 3]
|
|
13797
|
+
sage: U == B * B.H
|
|
13798
|
+
True
|
|
13799
|
+
sage: U = matrix(GF(3**2), [[0, 1, 2], [1, 0, 1], [2, 1, 0]])
|
|
13800
|
+
sage: B = U.cholesky(extended=True); B
|
|
13801
|
+
[2*z2 2 0]
|
|
13802
|
+
[2*z2 1 0]
|
|
13803
|
+
[ 0 1 z2]
|
|
13804
|
+
sage: U == B * B.H
|
|
13805
|
+
True
|
|
13806
|
+
|
|
13174
13807
|
TESTS:
|
|
13175
13808
|
|
|
13176
13809
|
This verifies that :issue:`11274` is resolved::
|
|
@@ -13217,7 +13850,22 @@ cdef class Matrix(Matrix1):
|
|
|
13217
13850
|
sage: all( matrix(R,[]).cholesky().is_immutable() # needs sage.rings.number_field
|
|
13218
13851
|
....: for R in (RR,CC,RDF,CDF,ZZ,QQ,AA,QQbar) )
|
|
13219
13852
|
True
|
|
13853
|
+
|
|
13854
|
+
Perform the extended decomposition over finite fields, which may result in non upper/lower triangular matrices::
|
|
13855
|
+
|
|
13856
|
+
sage: # needs sage.rings.finite_rings
|
|
13857
|
+
sage: A = matrix(GF(11**2),[[1,4,7],[4,1,4],[7,4,1]])
|
|
13858
|
+
sage: B = A.cholesky(extended=True)
|
|
13859
|
+
sage: A == B * B.H
|
|
13860
|
+
True
|
|
13861
|
+
sage: A = matrix(GF(3**2), [[0, 1, 2], [1, 0, 1], [2, 1, 0]])
|
|
13862
|
+
sage: B = A.cholesky(extended=True)
|
|
13863
|
+
sage: A == B * B.H
|
|
13864
|
+
True
|
|
13220
13865
|
"""
|
|
13866
|
+
if extended:
|
|
13867
|
+
return self._cholesky_extended_ff()
|
|
13868
|
+
|
|
13221
13869
|
cdef Matrix C # output matrix
|
|
13222
13870
|
C = self.fetch('cholesky')
|
|
13223
13871
|
if C is not None:
|
|
@@ -15476,6 +16124,10 @@ cdef class Matrix(Matrix1):
|
|
|
15476
16124
|
Return the conjugate of self, i.e. the matrix whose entries are the
|
|
15477
16125
|
conjugates of the entries of ``self``.
|
|
15478
16126
|
|
|
16127
|
+
.. SEEALSO::
|
|
16128
|
+
|
|
16129
|
+
:attr:`C`
|
|
16130
|
+
|
|
15479
16131
|
EXAMPLES::
|
|
15480
16132
|
|
|
15481
16133
|
sage: # needs sage.rings.complex_double sage.symbolic
|
|
@@ -15531,6 +16183,10 @@ cdef class Matrix(Matrix1):
|
|
|
15531
16183
|
though there is substantial variation and some confusion with
|
|
15532
16184
|
the use of that term.
|
|
15533
16185
|
|
|
16186
|
+
.. SEEALSO::
|
|
16187
|
+
|
|
16188
|
+
:meth:`conjugate`, :meth:`~.Matrix_dense.transpose`, :attr:`H`
|
|
16189
|
+
|
|
15534
16190
|
OUTPUT:
|
|
15535
16191
|
|
|
15536
16192
|
A matrix formed by taking the complex conjugate of every entry
|
|
@@ -15958,7 +16614,11 @@ cdef class Matrix(Matrix1):
|
|
|
15958
16614
|
"""
|
|
15959
16615
|
d = self.smith_form(transformation=False)
|
|
15960
16616
|
r = min(self.nrows(), self.ncols())
|
|
15961
|
-
|
|
16617
|
+
ed = [d[i, i] for i in range(r)]
|
|
16618
|
+
try:
|
|
16619
|
+
return [x.canonical_associate()[0] for x in ed]
|
|
16620
|
+
except (AttributeError, TypeError):
|
|
16621
|
+
return ed
|
|
15962
16622
|
|
|
15963
16623
|
def smith_form(self, transformation=True, integral=None, exact=True):
|
|
15964
16624
|
r"""
|
|
@@ -16138,7 +16798,7 @@ cdef class Matrix(Matrix1):
|
|
|
16138
16798
|
sage: d, u, v = m.smith_form(); u * m * v == d
|
|
16139
16799
|
True
|
|
16140
16800
|
|
|
16141
|
-
Over local fields, we can request the transformation matrices to be integral
|
|
16801
|
+
Over local fields, we can request the transformation matrices to be integral::
|
|
16142
16802
|
|
|
16143
16803
|
sage: K = Qp(2, 5, print_mode='terse') # needs sage.rings.padics
|
|
16144
16804
|
sage: M = matrix(K, 2, 3, [1/2, 1, 2, 1/3, 1, 3]) # needs sage.rings.padics
|
|
@@ -18229,11 +18889,11 @@ cdef class Matrix(Matrix1):
|
|
|
18229
18889
|
the greatest common divisor of the determinants of all `r`-by-`r`
|
|
18230
18890
|
submatrices of `B` is `1`. [Sch1986]_, Ch. 21.4.
|
|
18231
18891
|
|
|
18232
|
-
|
|
18233
|
-
|
|
18234
|
-
See :meth:`~sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_unimodular` for
|
|
18892
|
+
See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_unimodular` for
|
|
18235
18893
|
the detailed documentation.
|
|
18236
18894
|
|
|
18895
|
+
.. SEEALSO:: :meth:`is_k_equimodular`, :meth:`is_strongly_unimodular`, :meth:`is_totally_unimodular`
|
|
18896
|
+
|
|
18237
18897
|
EXAMPLES::
|
|
18238
18898
|
|
|
18239
18899
|
sage: # needs sage.libs.cmr
|
|
@@ -18256,7 +18916,10 @@ cdef class Matrix(Matrix1):
|
|
|
18256
18916
|
|
|
18257
18917
|
A matrix is strongly unimodular if ``self`` and ``self.transpose()`` are both unimodular.
|
|
18258
18918
|
|
|
18259
|
-
|
|
18919
|
+
See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_strongly_unimodular` for
|
|
18920
|
+
the detailed documentation.
|
|
18921
|
+
|
|
18922
|
+
.. SEEALSO:: :meth:`is_unimodular`, :meth:`is_strongly_k_equimodular`
|
|
18260
18923
|
|
|
18261
18924
|
EXAMPLES::
|
|
18262
18925
|
|
|
@@ -18295,6 +18958,9 @@ cdef class Matrix(Matrix1):
|
|
|
18295
18958
|
- ``k``: ``self`` is equimodular with determinant gcd `k`
|
|
18296
18959
|
- ``None``: ``self`` is not equimodular for any `k`
|
|
18297
18960
|
|
|
18961
|
+
See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.equimodulus` for
|
|
18962
|
+
the detailed documentation.
|
|
18963
|
+
|
|
18298
18964
|
.. SEEALSO:: :meth:`is_k_equimodular`, :meth:`strong_equimodulus`
|
|
18299
18965
|
|
|
18300
18966
|
EXAMPLES::
|
|
@@ -18336,6 +19002,9 @@ cdef class Matrix(Matrix1):
|
|
|
18336
19002
|
- ``k``: ``self`` is `k`-equimodular
|
|
18337
19003
|
- ``None``: ``self`` is not `k`-equimodular for any `k`
|
|
18338
19004
|
|
|
19005
|
+
See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.strong_equimodulus` for
|
|
19006
|
+
the detailed documentation.
|
|
19007
|
+
|
|
18339
19008
|
.. SEEALSO:: :meth:`is_strongly_k_equimodular`, :meth:`equimodulus`
|
|
18340
19009
|
|
|
18341
19010
|
EXAMPLES::
|
|
@@ -18374,6 +19043,9 @@ cdef class Matrix(Matrix1):
|
|
|
18374
19043
|
In parts of the literature, a matrix with the above properties
|
|
18375
19044
|
is called *strictly* `k`-modular.
|
|
18376
19045
|
|
|
19046
|
+
See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_k_equimodular` for
|
|
19047
|
+
the detailed documentation.
|
|
19048
|
+
|
|
18377
19049
|
.. SEEALSO:: :meth:`is_unimodular`, :meth:`is_strongly_k_equimodular`,
|
|
18378
19050
|
:meth:`equimodulus`
|
|
18379
19051
|
|
|
@@ -18403,6 +19075,9 @@ cdef class Matrix(Matrix1):
|
|
|
18403
19075
|
A matrix is strongly `k`-equimodular if ``self`` and ``self.transpose()``
|
|
18404
19076
|
are both `k`-equimodular.
|
|
18405
19077
|
|
|
19078
|
+
See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_strongly_k_equimodular` for
|
|
19079
|
+
the detailed documentation.
|
|
19080
|
+
|
|
18406
19081
|
.. SEEALSO:: :meth:`is_k_equimodular`, :meth:`is_strongly_unimodular`,
|
|
18407
19082
|
:meth:`strong_equimodulus`
|
|
18408
19083
|
|
|
@@ -18452,6 +19127,9 @@ cdef class Matrix(Matrix1):
|
|
|
18452
19127
|
the support matrix of `M` for being graphic and
|
|
18453
19128
|
uses camion for testing whether `M` is signed correctly.
|
|
18454
19129
|
|
|
19130
|
+
See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_network_matrix` for
|
|
19131
|
+
the detailed documentation.
|
|
19132
|
+
|
|
18455
19133
|
EXAMPLES::
|
|
18456
19134
|
|
|
18457
19135
|
sage: # needs sage.libs.cmr
|
|
@@ -18523,11 +19201,14 @@ cdef class Matrix(Matrix1):
|
|
|
18523
19201
|
|
|
18524
19202
|
def is_conetwork_matrix(self, *args, **kwds):
|
|
18525
19203
|
r"""
|
|
18526
|
-
Return whether the matrix ``self`` over `\GF{3}` or
|
|
19204
|
+
Return whether the matrix ``self`` over `\GF{3}` or `\QQ` is a conetwork matrix.
|
|
18527
19205
|
|
|
18528
|
-
A matrix is conetwork if and only if its transpose is network.
|
|
19206
|
+
A matrix is a conetwork matrix if and only if its transpose is a network matrix.
|
|
19207
|
+
|
|
19208
|
+
See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_conetwork_matrix` for
|
|
19209
|
+
the detailed documentation.
|
|
18529
19210
|
|
|
18530
|
-
.. SEEALSO:: :meth:`is_network_matrix
|
|
19211
|
+
.. SEEALSO:: :meth:`is_network_matrix`
|
|
18531
19212
|
|
|
18532
19213
|
EXAMPLES::
|
|
18533
19214
|
|
|
@@ -18586,14 +19267,15 @@ cdef class Matrix(Matrix1):
|
|
|
18586
19267
|
- ``stop_when_nonTU`` -- boolean (default: ``True``);
|
|
18587
19268
|
whether to stop decomposing once not TU is determined.
|
|
18588
19269
|
|
|
18589
|
-
For a description of other parameters, see :meth:`_set_cmr_seymour_parameters`
|
|
18590
|
-
|
|
18591
19270
|
- ``row_keys`` -- a finite or enumerated family of arbitrary objects
|
|
18592
19271
|
that index the rows of the matrix
|
|
18593
19272
|
|
|
18594
19273
|
- ``column_keys`` -- a finite or enumerated family of arbitrary objects
|
|
18595
19274
|
that index the columns of the matrix
|
|
18596
19275
|
|
|
19276
|
+
See :meth:`sage.matrix.matrix_cmr_sparse.Matrix_cmr_sparse.is_totally_unimodular` for
|
|
19277
|
+
the detailed documentation.
|
|
19278
|
+
|
|
18597
19279
|
EXAMPLES::
|
|
18598
19280
|
|
|
18599
19281
|
sage: # needs sage.libs.cmr
|
|
@@ -18667,8 +19349,8 @@ cdef class Matrix(Matrix1):
|
|
|
18667
19349
|
│ │
|
|
18668
19350
|
GraphicNode (5×4) CographicNode (4×5)
|
|
18669
19351
|
|
|
18670
|
-
|
|
18671
|
-
and ``TreeFlagsStopNongraphic`` in CMR's ``test_regular.cpp
|
|
19352
|
+
These are tests ``TreeFlagsNorecurse``, ``TreeFlagsStopNoncographic``,
|
|
19353
|
+
and ``TreeFlagsStopNongraphic`` in CMR's ``test_regular.cpp``;
|
|
18672
19354
|
the underlying binary linear matroid is regular,
|
|
18673
19355
|
but the matrix is not totally unimodular::
|
|
18674
19356
|
|
|
@@ -18701,9 +19383,6 @@ cdef class Matrix(Matrix1):
|
|
|
18701
19383
|
"""
|
|
18702
19384
|
return self._matrix_cmr().is_totally_unimodular(*args, **kwds)
|
|
18703
19385
|
|
|
18704
|
-
def is_complement_totally_unimodular(self, *args, **kwds):
|
|
18705
|
-
return self._matrix_cmr().is_complement_totally_unimodular(*args, **kwds)
|
|
18706
|
-
|
|
18707
19386
|
def LLL_gram(self, flag=0):
|
|
18708
19387
|
"""
|
|
18709
19388
|
Return the LLL transformation matrix for this Gram matrix.
|
|
@@ -18865,6 +19544,10 @@ cdef class Matrix(Matrix1):
|
|
|
18865
19544
|
r"""
|
|
18866
19545
|
Return the conjugate-transpose (Hermitian) matrix.
|
|
18867
19546
|
|
|
19547
|
+
.. SEEALSO::
|
|
19548
|
+
|
|
19549
|
+
:meth:`conjugate_transpose`
|
|
19550
|
+
|
|
18868
19551
|
EXAMPLES::
|
|
18869
19552
|
|
|
18870
19553
|
sage: A = matrix(QQbar, [[ -3, 5 - 3*I, 7 - 4*I], # needs sage.rings.number_field
|
|
@@ -18875,7 +19558,7 @@ cdef class Matrix(Matrix1):
|
|
|
18875
19558
|
[ 5 + 3*I -1 - 6*I -3 - 6*I]
|
|
18876
19559
|
[ 7 + 4*I 3 - 5*I 5 - 1*I]
|
|
18877
19560
|
"""
|
|
18878
|
-
return self.
|
|
19561
|
+
return self.conjugate_transpose()
|
|
18879
19562
|
|
|
18880
19563
|
|
|
18881
19564
|
def _smith_diag(d, transformation=True):
|