Forum archive 2000-2006

Thomas Hagedorn - How not to display Zero or One as Coefficient in a Linear Equation

Thomas Hagedorn - How not to display Zero or One as Coefficient in a Linear Equation

by Arnold Pizer -
Number of replies: 0
inactiveTopicHow not to display Zero or One as Coefficient in a Linear Equation topic started 5/17/2005; 10:48:33 AM
last post 5/18/2005; 12:10:35 PM
userThomas Hagedorn - How not to display Zero or One as Coefficient in a Linear Equation  blueArrow
5/17/2005; 10:48:33 AM (reads: 1583, responses: 9)
We're writing some linear equation problems with randomized coefficients. Currently, if the coefficient is 0 or 1, we might display an equation like:

1x+0y+7z=8.

Is there an easy way to write the code so that the "1x" is just "x" and the "0y" doesn't appear? We've already considered creating the correct output string using many if, then statements, but that gets very complicated for a 3 x3 or 4 x 5 system.

-Tom

<| Post or View Comments |>


userBob Byerly - Re: How not to display Zero or One as Coefficient in a Linear Equation  blueArrow
5/17/2005; 11:36:56 AM (reads: 1861, responses: 0)
Maybe someone has an easier solution, but here's an example of a function I wrote for some problems to display linear systems. Given a matrix equation of the form Ax=b, it takes A and b as arguments and returns a TeX representation of the corresponding system of linear equations, with terms lined up as expected. It does simplify terms with coefficients of 1 or 0 as Tom asks. Unfortunately it's hardwired to used x_1, x_2, etc. as variable names rather than x, y, ... For some reason (I forget why now), I chose to have it take as arguments matrices in the form used by MatrixReal1.pm rather than the form used by the Parser, which would have been more sensible:

 

sub Mat2System{
my $coeffs=shift();
my $vec = shift();
my ($srow,$scol) = $coeffs->dim();
my ($vrow,$vcol) = $vec->dim();
die "Wrong number of rows or columns" if (($vcol !=1) || ($vrow != $srow));
my $outstr="\begin{matrix}";
my $s;



for(my $j=0;$j<$srow;$j++){
$s=0;
for(my $i=0,my $vn=1;$i<$scol;$i++,$vn++){
my $a=$coeffs->element($j+1,$i+1);
if($a==0){
$outstr = $outstr . '&&';
}elsif($a>0){
if($a==1){$a="";}
if($s==0){$outstr = $outstr . "& $a x_{$vn}";$s=1;}
else{$outstr=$outstr . "&+& $a x_{$vn}";}
}else{
if($s == 1){
$a=-$a;
if($a==1){$a="";}
$outstr= $outstr . "&- &$a x_{$vn}";
}else{$outstr = $outstr . "& $a x_{$vn}";$s=1;}
}
}
$outstr = $outstr . "&=&" . $vec->element($j+1,1). "\\";
}
$outstr= $outstr . 'end{matrix}';
return $outstr;
}



 

Example of use:

 

$A1=Matrix->new_from_array_ref( [[2,-1],[0,3]]);
$solution1=[-2,3]; #What do we want the solution to be?
$x1=Matrix->new_from_array_ref([$solution1]);
$x1 = ~$x1; #transpose
$b1 = $A1*$x1;
$C1=Mat2System($A1,$b1);



BEGIN_TEXT
Solve the following system by back substitution:
[ $C1 ]
END_TEXT

It shouldn't be too hard to modify it to take a list of variable names as an extra argument or use a different list of variable names. I'm revising some problems now. I may try modifying this to use the Parser's matrices.

Bob

<| Post or View Comments |>


userJohn Jones - Re: How not to display Zero or One as Coefficient in a Linear Equation  blueArrow
5/17/2005; 12:14:09 PM (reads: 1861, responses: 0)
Hi,

If you want a system of equations with the x,y,... columns lined up, you may need something like what is above. If you have a single equation, you can use nicestring which is in webwork (in PGbasicmacros). You can get a string version of $a x + $b y + $c z + $d with

$polystring = nicestring([$a, $b, $c, $d],['x', 'y', 'z', '']);
I added a constant term just to illustrate how to produce it.

If you are setting up a system, then you can use this to produce left-hand sides and align on the equal signs, which would produce output like

2x + 3y - z = 5
4x + 5z = -7
-y + z = 0
This may or may not be good enough for what you want.

John

<| Post or View Comments |>


userDavide P. Cervone - Re: How not to display Zero or One as Coefficient in a Linear Equation  blueArrow
5/17/2005; 7:21:18 PM (reads: 1864, responses: 0)
If you use the new parser and create formula objects for your equations, there is a "reduce" method that will eliminate such redundencies. For example:

 

    loadMacros("Parser.pl");


Context()->variables->are(x=>'Real',y=>'Real',z=>'Real');
$f = Formula("1x+0y+7z")=>reduce;


BEGIN_TEXT
\(f(x,y,z) = \{$f->TeX\}\)
END_TEXT

would produce "f(x,y,z) = x + 7z" as its output.

You can include equalities in your formulas if you enable the equality operator (which is not enabled by default):

 

    Parser::BOP::equality::Allow();

Then you can do things like

 

    $f = Formula("1x+0y+7z=8")->reduce;

Some of the reduction rules may not be appropriate for what you are doing, but they can be turned on and off in the context. If you want to do that, let me know (it is not well documented, as is the case for most of the parser at the moment).

There is basic documentation on how to use the parser in ww2/doc/parser/docs. There still needs to be a lot more, but it is a start.

Davide

<| Post or View Comments |>


userDavide P. Cervone - Re: How not to display Zero or One as Coefficient in a Linear Equation  blueArrow
5/17/2005; 7:25:57 PM (reads: 1881, responses: 0)
PS, there is also a macro called FPOLY in the unionMacros.pl file in the macros directory of the Union problem library. This macro tries hard to eliminate coefficients of 1, 0 and -1 in things that look like polynomials. It does this via pattern matching (unlike the parser which does it symantically) so it is not perfect, but should handle your situation. For example, FPOLY("1x+0y+7z=8") would return "x+7z=8".

Davide

<| Post or View Comments |>


userLars Jensen - Re: How not to display Zero or One as Coefficient in a Linear Equation  blueArrow
5/18/2005; 1:50:10 AM (reads: 1887, responses: 1)
Here is another way to do this:

$a=random(-1,1,2);

$b=-1;

 

$ex="$a x + $b";$ex=~s/\+ -/- /s;$ex=~s/1 x /x /s;

Above code simply substitutes any

-1 x with -x,

1 x with x,

+ - with -

so an expression like \( $ex \) looks nice on the screen.

Lars.

<| Post or View Comments |>


userDavide P. Cervone - Re: How not to display Zero or One as Coefficient in a Linear Equation  blueArrow
5/18/2005; 8:11:56 AM (reads: 2156, responses: 0)
If I recall correctly, you will have to replace the \ with ~~ in the first substitution, because of the way PG handles slashes, if you use the technique in a pg file.

It will also convert 11 x to 1 x. I realize your values for $a don't go that high, but if someone tries to use this approach elsewhere, they could get caught by this. That is one of the hidden "gotchas" in using pattern matching rather than symantic analysis for doing this kind of thing.

Davide

<| Post or View Comments |>


userThomas Hagedorn - Re: How not to display Zero or One as Coefficient in a Linear Equation  blueArrow
5/18/2005; 10:48:29 AM (reads: 1815, responses: 0)
Many thanks, both for the various solutions and the discussion. I'll let you know how we fare implementing them.

Thanks, Tom

<| Post or View Comments |>


userThomas Hagedorn - Re: How not to display Zero or One as Coefficient in a Linear Equation  blueArrow
5/18/2005; 12:05:48 PM (reads: 1864, responses: 0)
I modified Bob's code so that you can specify your own variables. I'd like to simplify it further so that you simply specify $coef= [x,y] and the subroutine does the rest of the coding, but I couldn't get the code to work. The fact that the x and y are strings caused me problems. In any case, here's some code that works:

 

$A1=Matrix->new_from_array_ref( [[2,-1],[0,3]]); $solution1=[-2,3]; #What do we want the solution to be? $x1=Matrix->new_from_array_ref([$solution1]); $x1 = ~$x1; #transpose $b1 = $A1*$x1; $variablenames=Matrix->new_from_array_ref( [['x'],['y']] ); $C1=Mat2System($A1,$b1,$variablenames);

BEGIN_TEXT Solve the following system by back substitution: ( $C1 ) END_TEXT

sub Mat2System{ my $coeffs=shift(); my $vec = shift(); my $vname=shift(); my ($srow,$scol) = $coeffs->dim(); my ($vrow,$vcol) = $vec->dim(); my ($vnamerow,$vnamecol) = $vname->dim(); die "Wrong number of rows or columns" if (($vcol !=1) || ($vrow != $srow) || ($vnamecol !=1) || ($vrow != $vnamerow)); my $outstr="\begin{array}"; my $s;

$outstr = $outstr . '{r'; for(my $j=0; $j<$scol; $j++){ $outstr = $outstr . 'rr'; } $outstr = $outstr . 'r}';

for(my $j=0;$j<$srow;$j++){ $s=0; for(my $i=0,my $vn=1;$i<$scol;$i++,$vn++){ my $varname=$vname->element($vn,1); my $a=$coeffs->element($j+1,$i+1); if($a==0){ ## if coefficient is 0 then goto the next column by putting 2 &&'s $outstr = $outstr . '&&'; }elsif($a>0){ if($a==1){$a="";} if($s==0){$outstr = $outstr . "& $a \,$varname";$s=1; } else{$outstr=$outstr . "&+& $a \, $varname";} }else{ if($s == 1){ $a=-$a; if($a==1){$a="";} $outstr= $outstr . "&- &$a \,$varname"; }else{$outstr = $outstr . "& $a \, $varname";$s=1;} } } $outstr = $outstr . "&=&" . $vec->element($j+1,1). "\\"; } $outstr= $outstr . ' end{array}'; return $outstr; }

<| Post or View Comments |>


userThomas Hagedorn - Re: How not to display Zero or One as Coefficient in a Linear Equation  blueArrow
5/18/2005; 12:10:35 PM (reads: 1856, responses: 0)
Here's that code again in a more readable format:

$A1=Matrix->new_from_array_ref( [[2,-1],[0,3]]);

$solution1=[-2,3]; #What do we want the solution to be?

$x1=Matrix->new_from_array_ref([$solution1]);

$x1 = ~$x1; #transpose

$b1 = $A1*$x1;

$variablenames=Matrix->new_from_array_ref( [['x'],['y']] );

$C1=Mat2System($A1,$b1,$variablenames);

BEGIN_TEXT

Solve the following system by back substitution:

( $C1 ) END_TEXT

sub Mat2System{

my $coeffs=shift();

my $vec = shift();

my $vname=shift();

my ($srow,$scol) = $coeffs->dim();

my ($vrow,$vcol) = $vec->dim();

my ($vnamerow,$vnamecol) = $vname->dim();

die "Wrong number of rows or columns" if (($vcol !=1) || ($vrow != $srow) || ($vnamecol !=1) || ($vrow != $vnamerow));

my $outstr="\begin{array}"; my $s;

$outstr = $outstr . '{r';

for(my $j=0; $j<$scol; $j++){ $outstr = $outstr . 'rr';} $outstr = $outstr . 'r}';

for(my $j=0;$j<$srow;$j++){ $s=0; for(my $i=0,my $vn=1;$i<$scol;$i++,$vn++){ my $varname=$vname->element($vn,1); my $a=$coeffs->element($j+1,$i+1); if($a==0){ ## if coefficient is 0 then goto the next column by putting 2 &&'s $outstr = $outstr . '&&'; }elsif($a>0){ if($a==1){$a="";} if($s==0){$outstr = $outstr . "& $a \,$varname";$s=1; } else{$outstr=$outstr . "&+& $a \, $varname";} }else{ if($s == 1){ $a=-$a; if($a==1){$a="";} $outstr= $outstr . "&- &$a \,$varname"; }else{$outstr = $outstr . "& $a \, $varname";$s=1;} }} $outstr = $outstr . "&=&" . $vec->element($j+1,1). "\\";} $outstr= $outstr . ' end{array}'; return $outstr; }

<| Post or View Comments |>