WeBWorK Problems

Question about randomization

Question about randomization

by Alasdair McAndrew -
Number of replies: 2
I know you can easily create a random value between two integers. However, I would like to be able to create two different values in a given range. More generally, is there any method which provides a random subset functionality, where I could pick a few distinct values from a given range?

Also: in Sage (or any other system), I can write a program which generates random matrices with determinant one, where both the matrix and its inverse have non-zero values between -9 and 9. (Basically I generate matrices with determinant one and keep going until I have one which satisfies those requirements.) Is it possible to do this in WeBWorK either by calling Sage, or by doing it natively (using the Matrix class of MathObjects, for example)?

Thanks!
In reply to Alasdair McAndrew

Re: Question about randomization

by Christopher Heckman -
I know you can easily create a random value between two integers. However, I would like to be able to create two different values in a given range.
$n1 = random (-9, 9);
do { $n2 = random (-9, 9); } while ($n1 == $n2);
More generally, is there any method which provides a random subset functionality, where I could pick a few distinct values from a given range?
More generally, you can use the NchooseK function from PGchoicemacros.pl to choose a subset of any set; the code would look something like

loadMacros ("PGchoicemacros.pl");

@p = NchooseK (8, 3);
@values = ("A", "B", "C", "D", "E", "F", "G", "H");
@subset = @values [@p];


This will choose a 3-element permutation of {A, B, C, D, E, F, G, H}.
Also: in Sage (or any other system), I can write a program which generates random matrices with determinant one, where both the matrix and its inverse have non-zero values between -9 and 9. (Basically I generate matrices with determinant one and keep going until I have one which satisfies those requirements.) Is it possible to do this in WeBWorK either by calling Sage, or by doing it natively (using the Matrix class of MathObjects, for example)?
I've written a sub that generates matrices of a given size with determinant +1 or -1, where the sizes of the entries aren't too big (n^2*mult). There's no guarantee on the sizes of the entries of the inverse, though.

random_pmDet1 (n, mult): returns a random nxn matrix whose entries are at most n^2*mult in absolute value

random_perm_matrix ( n ): returns a random nxn permutation matrix

sub random_pmDet1 { # random_pmDet1(n, mult)
   my ($n, $m) = @_;
   my (@L, @U, $i, $j);
   push @L, [(0) x $n] for 1 .. $n;
   push @U, [(0) x $n] for 1 .. $n;
   for ($i = 0; $i < $n; $i++) {
      $L[$i][$i] = non_zero_random (-1,1);
      $U[$i][$i] = 1;
      for ($j = $i + 1; $j < $n; $j++)
         { $U[$i][$j] = random (-$m, $m); $L[$j][$i] = random (-$m, $m); }
      }
   random_perm_matrix ($n) * Matrix (@L) * Matrix (@U);
   }


sub random_perm_matrix { # random_perm_matrix( n )
   my $n = shift;
   my ($i, $j, @P);
   my @permutation = NchooseK ($n, $n);
   push @P, [(0) x $n] for 1 .. $n;
   for ($i = 0; $i < $n; $i++) { $P[$i][$permutation[$i]] = 1; }
   Matrix (@P);
   }
In reply to Alasdair McAndrew

Re: Question about randomization

by Dick Lane -
# generate 2 random but distinct values between LO and HI
a = random(LO,HI,1)
do  {b = random(LO,HI,1)}  until  (a != b)

For whatever it is worth, I think "do ... until (a not-equal b)" is more obviously-correct than "do ... while (a equal b)".

In any event, my initial goal is usually having different magnitudes for problem parameters.  If I will allow parameters with different signs, it is usually done with
    a *= List_Random(-1,1)
    b *= List_Random(-1,1)
after having generated a and b to be distinct and positive.  (This lets me avoid having a=-3 and b=3 in situations where that might confuse some students.)

Somewhere between getting 3 and 5 distinct values, I switch to using NchooseK (after loading PGchoicemacros.pl).  On the other hand, I will often use an "until [FALSE]" construct when the exclusion is more stringent than merely avoiding duplication.

I have attached code in R to generate a rank-n integer matrix whose inverse is also an integer matrix.  The key is the auxiliary function Low(n) which produces a random lower-triangular integer matrix with +/-1 on its diagonal.  The main function computes the product of two independent uses of Low(n):
    nonSingular(n) = Low(n) * t(Low(n))

I have not explored ways to bound entries in either the generated nonSingular matrix or its inverse.  E.g.,
    a)  use severe bounds for entries in Low(n)
    b)  impose some sparseness constraints on Low(n)

Note: Evar Nering's text on Linear Algebra has an appendix "Matrices and Inverses with Integral Elements".  It begins with two pages discussing procedures and then presents some explicit examples.