|
62 | 62 | # (at your option) any later version.
|
63 | 63 | # https://www.gnu.org/licenses/
|
64 | 64 | # ****************************************************************************
|
| 65 | +from copy import copy |
65 | 66 |
|
66 | 67 | from sage.rings.ring import is_Ring
|
67 | 68 | import sage.matrix.matrix_space as matrix_space
|
|
72 | 73 | from sage.rings.rational_field import QQ
|
73 | 74 | from sage.rings.integer import Integer
|
74 | 75 | from sage.misc.misc_c import running_total
|
75 |
| -from copy import copy |
| 76 | +from sage.misc.prandom import randint, shuffle |
76 | 77 | from .constructor import matrix
|
77 |
| - |
78 | 78 | import sage.categories.pushout
|
79 | 79 |
|
80 | 80 |
|
@@ -2473,104 +2473,107 @@ def random_rref_matrix(parent, num_pivots):
|
2473 | 2473 |
|
2474 | 2474 | TESTS:
|
2475 | 2475 |
|
| 2476 | + Rank zero:: |
| 2477 | +
|
| 2478 | + sage: random_matrix(QQ, 1, 1, algorithm='echelon_form', num_pivots=0) |
| 2479 | + [0] |
| 2480 | +
|
2476 | 2481 | Rank of a matrix must be an integer. ::
|
2477 | 2482 |
|
2478 | 2483 | sage: random_matrix(QQ, 120, 56, algorithm='echelon_form', num_pivots=61/2)
|
2479 | 2484 | Traceback (most recent call last):
|
2480 | 2485 | ...
|
2481 |
| - TypeError: the number of pivots must be an integer. |
| 2486 | + TypeError: the number of pivots must be an integer |
2482 | 2487 |
|
2483 | 2488 | Matrices must be generated over exact fields. ::
|
2484 | 2489 |
|
2485 | 2490 | sage: random_matrix(RR, 40, 88, algorithm='echelon_form', num_pivots=39)
|
2486 | 2491 | Traceback (most recent call last):
|
2487 | 2492 | ...
|
2488 |
| - TypeError: the base ring must be exact. |
| 2493 | + TypeError: the base ring must be exact |
2489 | 2494 |
|
2490 | 2495 | Matrices must have the number of pivot columns be less than or equal to the number of rows. ::
|
2491 | 2496 |
|
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 |
2493 | 2498 | Traceback (most recent call last):
|
2494 | 2499 | ...
|
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 |
2496 | 2501 |
|
2497 | 2502 | Matrices must have the number of pivot columns be less than or equal to the number of columns. ::
|
2498 | 2503 |
|
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 |
2500 | 2505 | Traceback (most recent call last):
|
2501 | 2506 | ...
|
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 |
2503 | 2508 |
|
2504 | 2509 | Matrices must have the number of pivot columns be greater than zero. ::
|
2505 | 2510 |
|
2506 | 2511 | sage: random_matrix(QQ, 5, 4, algorithm='echelon_form', num_pivots=-1)
|
2507 | 2512 | Traceback (most recent call last):
|
2508 | 2513 | ...
|
2509 |
| - ValueError: the number of pivots must be zero or greater. |
| 2514 | + ValueError: the number of pivots must be zero or greater |
2510 | 2515 |
|
2511 | 2516 | AUTHOR:
|
2512 | 2517 |
|
2513 | 2518 | Billy Wonderly (2010-07)
|
2514 | 2519 | """
|
2515 | 2520 | import sage.probability.probability_distribution as pd
|
2516 |
| - from sage.misc.prandom import randint |
2517 | 2521 |
|
2518 | 2522 | try:
|
2519 | 2523 | num_pivots = ZZ(num_pivots)
|
2520 | 2524 | except TypeError:
|
2521 |
| - raise TypeError("the number of pivots must be an integer.") |
| 2525 | + raise TypeError("the number of pivots must be an integer") |
2522 | 2526 | 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") |
2524 | 2528 | ring = parent.base_ring()
|
2525 | 2529 | if not ring.is_exact():
|
2526 |
| - raise TypeError("the base ring must be exact.") |
| 2530 | + raise TypeError("the base ring must be exact") |
2527 | 2531 | num_row = parent.nrows()
|
2528 | 2532 | num_col = parent.ncols()
|
2529 | 2533 | 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) |
2531 | 2569 | 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() |
2574 | 2577 | return return_matrix
|
2575 | 2578 |
|
2576 | 2579 |
|
@@ -2692,7 +2695,7 @@ def random_echelonizable_matrix(parent, rank, upper_bound=None, max_tries=100):
|
2692 | 2695 | sage: random_matrix(RR, 3, 3, algorithm='echelonizable', rank=2)
|
2693 | 2696 | Traceback (most recent call last):
|
2694 | 2697 | ...
|
2695 |
| - TypeError: the base ring must be exact. |
| 2698 | + TypeError: the base ring must be exact |
2696 | 2699 |
|
2697 | 2700 | Works for rank==1, too. ::
|
2698 | 2701 |
|
|
0 commit comments