assign(M, [i, j], k) replaces M(i,j) with k.
random_vector (n, m) will generate a random vector of length n whose entries are at most m in absolute value
rand_pmDet1(n, m) will generate a random nxn matrix whose entries are bounded by a function of m (nm2, probably).
random_perm_matrix(n) generates a random nxn permutation matrix
zero_matrix(m,n) generates the mxn zero matrix.
rowop_multiplyrow (n, i, m)
rowop_swaprows (n, i, j)
rowop_addmultrow (n, i, j, m)
all generate elementary matrices (to simulate row operations); they all return nxn matrices. i and j represent relevant row numbers, and m is the multiplier.
random_rref (m, n, r, M, L)
random_ref (m, n, r, M, L)
generate random matrices which are in RREF or REF. The matrix returned is mxn and has rank r. The absolute values of non-pivot entries are at most M. L is a list of columns required to have pivots. Thus,
B = random_rref (4, 5, 3, 2, (1,3)) generates a 4x5 matrix B in RREF with rank 3, whose entries are all at most 2 in absolute value, and has pivots in columns 1 and 3. A matrix which is 4x5 and has rank 3 can be created by multiplying B on the left by an invertible 4x4 matrix (not too difficult to code; I'll probably add it later). WARNING: No common-sense checking is done, so make sure you send legitimate values (r <= min(m,n), for instance).
make_RHS (A, r, m, c?): creates a right-hand side B for a system of linear equations. A is the coefficient matrix (in REF or RREF), r is its rank, m is a bound on the size of the entries of B, and the system is made consistent iff c is nonzero. (Yes, my code for finding the rank could be used to write a version that calculates r on its own, but typically when you are writing problems, you will choose r yourself, so you may as well send along information that you already have.)
num_zeroCols (A) is the number of all-zero columns of A.
Mat2System is an item on the wish list. It takes a matrix A, a vector B, and a list of variables L, and sets up the system of linear equations nicely. Note that the order of arguments has been changed; an example of the proper way to use it is:
$s = Mat2System ($A, $b, qw(x y z));
...
Consider the system of linear equations \[$s\]
...
In case you don't know everything about Perl (I for one don't), the qw will take what follows and turn it into a list of strings:
qw(x y z) ---> ("x", "y", "z");
You can even put in subscripts, as in: qw(x_1 x_2 x_3 x_4)
That's all for now.
sub assign { # assign ($L, [0,2], 13); NOT mine</div><div> my $self = shift; my $index = shift; my $x = shift;</div><div> my $i = shift(@$index);</div><div> if (scalar(@$index)) {assign($self->{data}[$i],$index,$x)}
else {$self->{data}[$i] = Value::makeValue($x)}
}
sub random_vector { # rand_vector (n, mult)</div><div> my $n = shift; my $m = shift;</div><div> my $M = Value::Matrix->I($n);</div><div> for ($i = 0; $i < $n; $i++) { assign ($M, [$i, 0], random(-$m,$m)); }
return Vector($M->column(1));
}
sub rand_pmDet1 { # rand_pmDet1(n, mult)</div><div> my $n = shift; my $m = shift;</div><div> my $L = Value::Matrix->I($n);</div><div> my $U = Value::Matrix->I($n);</div><div> for ($i = 0; $i < $n; $i++) { </div><div> assign ($L, [$i, $i], non_zero_random(-1,1));</div><div> for ($j = $i + 1; $j < $n; $j++) { </div><div> assign ($U, [$i, $j], random(-$m, $m));</div><div> assign ($L, [$j, $i], random (-$m, $m)); </div><div> }
}
return random_perm_matrix ($n) * $L * $U;
}
sub random_perm_matrix { # random_perm_matrix(n)</div><div> my $n = shift;</div><div> my $P = Value::Matrix->I($n);</div><div> my $i, $j;</div><div> my @permutation = NchooseK($n,$n);</div><div> for ($i = 1; $i <= $n; $i++) { </div><div> assign($P, [$i, $i], 0); </div><div> assign($P, [$i, $permutation[$i]], 1);</div><div> }
$P;
}
sub zero_matrix { # zero_matrix(m,n)</div><div> my $m = shift; my $n = shift;</div><div> my $M = Value::Matrix->I($m);</div><div> assign ($M, [0,0], 0);</div><div> my $A = $M -> column(1);</div><div> for ($i = 0; $i < $m; $i++) { for ($j = 0; $j < $n; $j++) { assign ($A, [$i,$j], 0); } }
$A
}
sub rowop_multiplyrow { # rowop_multiplyrow (n, i, M);</div><div> my $A = Value::Matrix->I(shift);</div><div> my $i = shift;</div><div> assign ($A, [$i - 1, $i - 1], shift);</div><div> $A;</div><div> }
sub rowop_swaprows { # rowop_swaprows (n, i, j);</div><div> my $A = Value::Matrix->I(shift);</div><div> my $i = shift; my $j = shift;</div><div> assign ($A, [$i - 1, $i - 1], 0);</div><div> assign ($A, [$j - 1, $j - 1], 0);</div><div> assign ($A, [$i - 1, $j - 1], 1);</div><div> assign ($A, [$j - 1, $i - 1], 1);</div><div> $A;</div><div> }
sub rowop_addmultrow { # rowop_swaprows (n, i, j, M);</div><div> my $A = Value::Matrix->I(shift);</div><div> my $i = shift; my $j = shift;</div><div> my $M = shift;</div><div> assign ($A, [$i - 1, $j - 1], $M);</div><div> $A;</div><div> }
sub multiple { my $m = non_zero_random(-5,5); redo if ($m == 1); $m; }
sub random_rref { # random_rref (m, n, r, M, L);</div><div> my $m = shift; my $n = shift; my $r = shift; my $M = shift;</div><div> my @L = @_;</div><div> my @Lrest, $i, $indextoremove, $ro, $c;</div><div> my $Llength = scalar @L;</div><div> my @pivotCols;</div><div> for ($i = 0; $i < $n; $i++) { $Lrest[$i] = $i + 1; }
for ($i = 0; $i < $Llength; $i++) {</div><div> $pivotCols[$i] = $L[$i];</div><div> for ($j = 0; $j < $n - $i; $j++) </div><div> { if ($L[$i] == $Lrest[$j]) { $indextoremove = $j; } }
splice (@Lrest, $indextoremove, 1);
}
my @restOfPivots = NchooseK ($n - $Llength, $r - $Llength);
for ($i = 0; $i < $r - $Llength; $i++)
{ $pivotCols[$i + $Llength] = $Lrest[$restOfPivots[$i]]; }
@pivotCols = num_sort (@pivotCols);
$R = Value::Matrix->I($m);
for ($i = 0; $i < $m; $i ++)
{ for ($j = 0; $j < $n; $j ++) { assign ($R, [$i,$j], 0); } }
for ($i = 0; $i < $r; $i ++) { assign ($R, [$i, $pivotCols[$i] - 1], 1); }
for ($i = 0; $i < $r - 1; $i++) {</div><div> for ($c = $pivotCols[$i] + 1; $c < $pivotCols[$i + 1]; $c ++) { </div><div> for ($ro = 0; $ro <= $i; $ro++) </div><div> { assign ($R, [$ro, $c-1], random(-$M,$M)); }
}
}
for ($c = $pivotCols[$r - 1] + 1; $c <= $n; $c++) {</div><div> for ($ro = 0; $ro < $r; $ro++) </div><div> { assign ($R, [$ro, $c - 1], random(-$M, $M)); }
}
$R;
}
sub random_ref { # random_rref (m, n, r, M, L);</div><div> my $m = shift; my $n = shift; my $r = shift; my $M = shift;</div><div> my @L = @_;</div><div> my @Lrest, $i, $indextoremove, $ro, $c;</div><div> my $Llength = scalar @L;</div><div> my @pivotCols;</div><div> for ($i = 0; $i < $n; $i++) { $Lrest[$i] = $i + 1; }
for ($i = 0; $i < $Llength; $i++) {</div><div> $pivotCols[$i] = $L[$i];</div><div> for ($j = 0; $j < $n - $i; $j++) </div><div> { if ($L[$i] == $Lrest[$j]) { $indextoremove = $j; } }
splice (@Lrest, $indextoremove, 1);
}
my @restOfPivots = NchooseK ($n - $Llength, $r - $Llength);
for ($i = 0; $i < $r - $Llength; $i++)
{ $pivotCols[$i + $Llength] = $Lrest[$restOfPivots[$i]]; }
@pivotCols = num_sort (@pivotCols);
$R = Value::Matrix->I($m);
for ($i = 0; $i < $m; $i ++)
{ for ($j = 0; $j < $n; $j ++) { assign ($R, [$i,$j], 0); } }
for ($i = 0; $i < $r; $i ++) { </div><div> assign ($R, [$i, $pivotCols[$i] - 1], 1); </div><div> for ($ro = 0; $ro < $i; $ro++) </div><div> { assign ($R, [$ro, $pivotCols[$i] - 1], random (-$M, $M)); }
}
for ($i = 0; $i < $r - 1; $i++) {</div><div> for ($c = $pivotCols[$i] + 1; $c < $pivotCols[$i + 1]; $c ++) { </div><div> for ($ro = 0; $ro <= $i; $ro++) </div><div> { assign ($R, [$ro, $c-1], random(-$M,$M)); }
}
}
for ($c = $pivotCols[$r - 1] + 1; $c <= $n; $c++) {</div><div> for ($ro = 0; $ro < $r; $ro++) </div><div> { assign ($R, [$ro, $c - 1], random(-$M, $M)); }
}
$R;
}
sub make_RHS { # make_RHS (LHS, rank, multiplier, consistent?)</div><div> my $A = shift; my $r = shift; my $m = shift; my $b = shift;</div><div> my $mA = ($A->dimensions)[0];</div><div> my $RHS = zero_matrix ($mA, 0);</div><div> for ($i = 0; $i < $r; $i++) { assign ($RHS, [$i,0], random(-$m, $m)); }
if ((! $b) && ($r < $mA)) { assign ($RHS, [$r,0], 1); }
$RHS;
}
sub num_zeroCols { # num_zeroCols (A)</div><div> my $A = shift;</div><div> my $s, $nz, $m;</div><div> $nz = 0;</div><div> $m = ($A->dimensions)[0];</div><div> for ($i = 1; $i <= ($A->dimensions)[1]; $i++) {</div><div> $s = 0;</div><div> for ($j = 1; $j <= $m; $j++) { $s += ($A->element($j,$i)) ** 2; }
if ($s < 10 ** (-8)) { $nz ++; }
}
$nz;
}
sub Mat2System{ # Mat2System (A, b, qw(x y z w))</div><div> my $coeffs = shift;</div><div> my $vname = shift;</div><div> my @vec = @_;</div><div> my $srow = ($coeffs->dimensions)[0];</div><div> my $scol = ($coeffs->dimensions)[1];</div><div> my $vnamerow = scalar @vec;</div><div> my $vrow = ($vname->dimensions)[0];</div><div> die "Wrong number of rows or columns2" if ($vrow != $srow);</div><div> die "Wrong number of rows or columns4" if ($scol != $vnamerow);</div><div> my $outstr="\begin{array}";
my $s;
$outstr .= '{r';</div><div> for (my $j=0; $j<$scol; $j++) { $outstr .= 'rr'; }
$outstr .= 'r}';
for (my $j = 0; $j < $srow; $j ++) { </div><div> $s = 0; </div><div> for (my $i = 0, my $vn = 1; $i < $scol; $i++, $vn++) { </div><div> my $varname = $vec [$vn - 1];</div><div> my $a=$coeffs->element($j+1,$i+1); </div><div> if ($a == 0) {</div><div> if (($s > 0) || ($i < $scol - 1)) { $outstr .= '&&'; }
else { $outstr .= '&0'; }
}
elsif ($a > 0) { </div><div> if ($a == 1) { $a = ""; }
if ($s==0) {$outstr .= "& $a \,$varname"; $s = 1; }
else {$outstr .= "&+& $a \, $varname"; }
}
else { </div><div> if ($s == 1) { </div><div> $a = -$a; </div><div> if ($a == 1) { $a = ""; }
$outstr .= "&- &$a \,$varname";
}
else {</div><div> if ($a == -1) { $a = "-"; }
$outstr = $outstr . "& $a \, $varname"; $s = 1;
}
}
}
$outstr .= "&=&" . $vname->element($j+1, 1). "\\";
}
$outstr . ' \end{array}';
}