Skip to content

Commit 1943799

Browse files
author
Release Manager
committed
gh-36313: tentative of random subset for random matrix trying to do something for #35664 ; not yet good ### 📝 Checklist - [x] The title is concise, informative, and self-explanatory. - [x] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [x] I have updated the documentation accordingly. URL: #36313 Reported by: Frédéric Chapoton Reviewer(s): David Coudert, Frédéric Chapoton
2 parents 2f1a76d + 1953d8f commit 1943799

File tree

1 file changed

+60
-57
lines changed

1 file changed

+60
-57
lines changed

src/sage/matrix/special.py

Lines changed: 60 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
# (at your option) any later version.
6363
# https://www.gnu.org/licenses/
6464
# ****************************************************************************
65+
from copy import copy
6566

6667
from sage.rings.ring import is_Ring
6768
import sage.matrix.matrix_space as matrix_space
@@ -72,9 +73,8 @@
7273
from sage.rings.rational_field import QQ
7374
from sage.rings.integer import Integer
7475
from sage.misc.misc_c import running_total
75-
from copy import copy
76+
from sage.misc.prandom import randint, shuffle
7677
from .constructor import matrix
77-
7878
import sage.categories.pushout
7979

8080

@@ -2473,104 +2473,107 @@ def random_rref_matrix(parent, num_pivots):
24732473
24742474
TESTS:
24752475
2476+
Rank zero::
2477+
2478+
sage: random_matrix(QQ, 1, 1, algorithm='echelon_form', num_pivots=0)
2479+
[0]
2480+
24762481
Rank of a matrix must be an integer. ::
24772482
24782483
sage: random_matrix(QQ, 120, 56, algorithm='echelon_form', num_pivots=61/2)
24792484
Traceback (most recent call last):
24802485
...
2481-
TypeError: the number of pivots must be an integer.
2486+
TypeError: the number of pivots must be an integer
24822487
24832488
Matrices must be generated over exact fields. ::
24842489
24852490
sage: random_matrix(RR, 40, 88, algorithm='echelon_form', num_pivots=39)
24862491
Traceback (most recent call last):
24872492
...
2488-
TypeError: the base ring must be exact.
2493+
TypeError: the base ring must be exact
24892494
24902495
Matrices must have the number of pivot columns be less than or equal to the number of rows. ::
24912496
2492-
sage: C=random_matrix(ZZ, 6,4, algorithm='echelon_form', num_pivots=7); C
2497+
sage: C = random_matrix(ZZ, 6,4, algorithm='echelon_form', num_pivots=7); C
24932498
Traceback (most recent call last):
24942499
...
2495-
ValueError: number of pivots cannot exceed the number of rows or columns.
2500+
ValueError: number of pivots cannot exceed the number of rows or columns
24962501
24972502
Matrices must have the number of pivot columns be less than or equal to the number of columns. ::
24982503
2499-
sage: D=random_matrix(QQ, 1,3, algorithm='echelon_form', num_pivots=5); D
2504+
sage: D = random_matrix(QQ, 1,3, algorithm='echelon_form', num_pivots=5); D
25002505
Traceback (most recent call last):
25012506
...
2502-
ValueError: number of pivots cannot exceed the number of rows or columns.
2507+
ValueError: number of pivots cannot exceed the number of rows or columns
25032508
25042509
Matrices must have the number of pivot columns be greater than zero. ::
25052510
25062511
sage: random_matrix(QQ, 5, 4, algorithm='echelon_form', num_pivots=-1)
25072512
Traceback (most recent call last):
25082513
...
2509-
ValueError: the number of pivots must be zero or greater.
2514+
ValueError: the number of pivots must be zero or greater
25102515
25112516
AUTHOR:
25122517
25132518
Billy Wonderly (2010-07)
25142519
"""
25152520
import sage.probability.probability_distribution as pd
2516-
from sage.misc.prandom import randint
25172521

25182522
try:
25192523
num_pivots = ZZ(num_pivots)
25202524
except TypeError:
2521-
raise TypeError("the number of pivots must be an integer.")
2525+
raise TypeError("the number of pivots must be an integer")
25222526
if num_pivots < 0:
2523-
raise ValueError("the number of pivots must be zero or greater.")
2527+
raise ValueError("the number of pivots must be zero or greater")
25242528
ring = parent.base_ring()
25252529
if not ring.is_exact():
2526-
raise TypeError("the base ring must be exact.")
2530+
raise TypeError("the base ring must be exact")
25272531
num_row = parent.nrows()
25282532
num_col = parent.ncols()
25292533
if num_pivots > num_row or num_pivots > num_col:
2530-
raise ValueError("number of pivots cannot exceed the number of rows or columns.")
2534+
raise ValueError("number of pivots cannot exceed the number of rows or columns")
2535+
2536+
if num_pivots == 0:
2537+
return parent.zero()
2538+
2539+
one = ring.one()
2540+
# Create a matrix of the desired size to be modified and then returned.
2541+
return_matrix = copy(parent.zero_matrix())
2542+
2543+
# No harm if no pivots at all.
2544+
subset = list(range(1, num_col))
2545+
shuffle(subset)
2546+
pivots = [0] + sorted(subset[:num_pivots - 1])
2547+
2548+
# Use the list of pivot columns to set the pivot entries of the return_matrix to leading ones.
2549+
for pivot_row, pivot in enumerate(pivots):
2550+
return_matrix[pivot_row, pivot] = one
2551+
if ring is QQ or ring is ZZ:
2552+
# Keep track of the non-pivot columns by using the pivot_index, start at the first column to
2553+
# the right of the initial pivot column, go until the first column to the left of the next
2554+
# pivot column.
2555+
for pivot_index in range(num_pivots - 1):
2556+
for non_pivot_column_index in range(pivots[pivot_index] + 1, pivots[pivot_index + 1]):
2557+
entry_generator1 = pd.RealDistribution("beta", [6, 4])
2558+
# Experimental distribution used to generate the values.
2559+
for non_pivot_column_entry in range(pivot_index + 1):
2560+
sign1 = (2 * randint(0, 1) - 1)
2561+
return_matrix[non_pivot_column_entry, non_pivot_column_index] = sign1 * int(entry_generator1.get_random_element() * ((1 - non_pivot_column_entry / return_matrix.ncols()) * 7))
2562+
# Use index to fill entries of the columns to the right of the last pivot column.
2563+
for rest_non_pivot_column in range(pivots[num_pivots - 1] + 1, num_col):
2564+
entry_generator2 = pd.RealDistribution("beta", [2.6, 4])
2565+
# experimental distribution to generate small values.
2566+
for rest_entries in range(num_pivots):
2567+
sign2 = (2 * randint(0, 1) - 1)
2568+
return_matrix[rest_entries, rest_non_pivot_column] = sign2 * int(entry_generator2.get_random_element() * 5)
25312569
else:
2532-
one = ring.one()
2533-
# Create a matrix of the desired size to be modified and then returned.
2534-
return_matrix = copy(parent.zero_matrix())
2535-
pivots = [0] #Force first column to be a pivot. No harm if no pivots at all.
2536-
# Probability distribution for the placement of leading one's.
2537-
pivot_generator = pd.RealDistribution("beta", [1.6, 4.3])
2538-
while len(pivots) < num_pivots:
2539-
pivot_column = int(pivot_generator.get_random_element() * num_col)
2540-
if pivot_column not in pivots:
2541-
pivots.append(pivot_column)
2542-
pivots.sort()
2543-
pivot_row = 0
2544-
# Use the list of pivot columns to set the pivot entries of the return_matrix to leading ones.
2545-
while pivot_row < num_pivots:
2546-
return_matrix[pivot_row, pivots[pivot_row]] = one
2547-
pivot_row += 1
2548-
if ring is QQ or ring is ZZ:
2549-
# Keep track of the non-pivot columns by using the pivot_index, start at the first column to
2550-
# the right of the initial pivot column, go until the first column to the left of the next
2551-
# pivot column.
2552-
for pivot_index in range(num_pivots-1):
2553-
for non_pivot_column_index in range(pivots[pivot_index]+1, pivots[pivot_index+1]):
2554-
entry_generator1 = pd.RealDistribution("beta", [6, 4])
2555-
# Experimental distribution used to generate the values.
2556-
for non_pivot_column_entry in range(pivot_index+1):
2557-
sign1 = (2*randint(0,1)-1)
2558-
return_matrix[non_pivot_column_entry,non_pivot_column_index]=sign1*int(entry_generator1.get_random_element()*((1-non_pivot_column_entry/return_matrix.ncols())*7))
2559-
# Use index to fill entries of the columns to the right of the last pivot column.
2560-
for rest_non_pivot_column in range(pivots[num_pivots-1]+1,num_col):
2561-
entry_generator2=pd.RealDistribution("beta",[2.6,4])
2562-
# experimental distribution to generate small values.
2563-
for rest_entries in range(num_pivots):
2564-
sign2=(2*randint(0,1)-1)
2565-
return_matrix[rest_entries,rest_non_pivot_column]=sign2*int(entry_generator2.get_random_element()*5)
2566-
else:
2567-
for pivot_index in range(num_pivots-1):
2568-
for non_pivot_column_index in range(pivots[pivot_index]+1,pivots[pivot_index+1]):
2569-
for non_pivot_column_entry in range(pivot_index+1):
2570-
return_matrix[non_pivot_column_entry,non_pivot_column_index]=ring.random_element()
2571-
for rest_non_pivot_column in range(pivots[num_pivots-1]+1,num_col):
2572-
for rest_entries in range(num_pivots):
2573-
return_matrix[rest_entries,rest_non_pivot_column]=ring.random_element()
2570+
for pivot_index in range(num_pivots - 1):
2571+
for non_pivot_column_index in range(pivots[pivot_index] + 1, pivots[pivot_index + 1]):
2572+
for non_pivot_column_entry in range(pivot_index + 1):
2573+
return_matrix[non_pivot_column_entry, non_pivot_column_index] = ring.random_element()
2574+
for rest_non_pivot_column in range(pivots[num_pivots - 1] + 1, num_col):
2575+
for rest_entries in range(num_pivots):
2576+
return_matrix[rest_entries, rest_non_pivot_column] = ring.random_element()
25742577
return return_matrix
25752578

25762579

@@ -2692,7 +2695,7 @@ def random_echelonizable_matrix(parent, rank, upper_bound=None, max_tries=100):
26922695
sage: random_matrix(RR, 3, 3, algorithm='echelonizable', rank=2)
26932696
Traceback (most recent call last):
26942697
...
2695-
TypeError: the base ring must be exact.
2698+
TypeError: the base ring must be exact
26962699
26972700
Works for rank==1, too. ::
26982701

0 commit comments

Comments
 (0)