Parent Directory | Revision Log

Revision **6134** -
(**download**)
(**as text**)
(**annotate**)

*Sat Oct 3 16:39:42 2009 UTC*
(10 years, 3 months ago)
by *dpvc*

File size: 6191 byte(s)

File size: 6191 byte(s)

Reduction rule should be off by default

1 ################################################################################ 2 # WeBWorK Online Homework Delivery System 3 # Copyright © 2000-2009 The WeBWorK Project, http://openwebwork.sf.net/ 4 # $CVSHeader: pg/macros/parserPrime.pl,v 1.2 2009/10/03 15:58:49 dpvc Exp $ 5 # 6 # This program is free software; you can redistribute it and/or modify it under 7 # the terms of either: (a) the GNU General Public License as published by the 8 # Free Software Foundation; either version 2, or (at your option) any later 9 # version, or (b) the "Artistic License" which comes with this package. 10 # 11 # This program is distributed in the hope that it will be useful, but WITHOUT 12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the 14 # Artistic License for more details. 15 ################################################################################ 16 17 =head1 NAME 18 19 parserPrime.pl - defines a prime operator (') to perform differentiation 20 (can be used in student answers as well). 21 22 =head1 DESCRIPTION 23 24 This file defines the code necessary to make the prime (') operator perform 25 differentiation within a Formula object. For example, Formula("(x^2)'") would 26 equal Formula("2*x"), and Formula("(x^2)''") would equal Real(2). The context 27 also includes reduction rules to replace the prime notaiton by the actual 28 derivative. 29 30 To accomplish this, put the line 31 32 loadMacros("parserPrime.pl"); 33 34 at the beginning of your problem file, then set the Context to the one you wish 35 to use in the problem. Then use the command: 36 37 parser::Prime->Enable; 38 39 (You can also pass the Enable command a context pointer if you wish to 40 alter a context other than the current one.) 41 42 Once this is done, you will be able to enter primes in your Formulas 43 to refer to differentiation. For example: 44 45 Formula("(3x^2+2x+1)'") 46 47 would mean the derivative of 3x^2+2x+1 and would be equivalent to 48 49 Formula("3*2*x+2") 50 51 The variable of differentiation is taken from the variables used in 52 the formula being differentiated. If there is more than one variable 53 used, the first one alphabetically is used. For example 54 55 Formula("(ln(x))' + (x^2+3y)'") 56 57 would produce the equivalent to 58 59 Formula("(1/x) + (2*x+0)"). 60 61 This can have unexpected results, however, since. 62 63 Formula("(x^2)' + (y^2)'") 64 65 would generate 66 67 Formula("2*x + 2*y") 68 69 which may not be what you want. In order to specify the variable for 70 differentiation, you can list it in the Enable() call. For example: 71 72 parser::Prime->Enable("x"); 73 74 would make 75 76 Formula("(x^2)' + (y^2)'") 77 78 generate 79 80 Formula("2*x + 0") 81 82 rather than the default 2x+2y. 83 84 The prime operator also defines a reduction rule that allows the prime 85 notation to be replaced by the actual derivative when the Formula is 86 reduced. This is off by default, but you can set it via 87 88 Context()->reduction->set("(f)'"=>1); 89 90 so that it will be on for all reductions, or specify it for a single 91 reduction as follows: 92 93 $f = Formula("(x^2)'")->reduce("(f)'"=>1); 94 95 to obtain $f as Formula("2*x"). 96 97 Note that once the prime has been added to the Context, student 98 answers will be allowed to include primes as well, so if you want 99 students to actually perform the differentiation themselves, you may 100 wish to disable the prime at the end of the problem (so it will not be 101 active while student answers are being parsed). To do that use 102 103 parser::Prime->Disable; 104 105 (You can pass Disable a context pointer to remove the prime operator 106 from a context other than the current one.) 107 108 =cut 109 110 sub _parserPrime_init {}; # don't load a second time 111 112 ########################################## 113 # 114 # Package to enable and disable the prime operator 115 # 116 package parser::Prime; 117 118 # 119 # Add prime to the given or current context 120 # 121 sub Enable { 122 my $self = shift; my $x = shift; 123 my $context = main::Context(); 124 if (Value::isContext($x)) {$context = $x; $x = shift} 125 $context->operators->add("'"=>{ 126 precedence => 8.5, associativity => "right", type => "unary", string => "'", 127 class => "parser::Prime::UOP::prime", isCommand => 1 128 }); 129 $context->reduction->set("(f)'" => 0); 130 $context->flags->set(prime_variable => $x) if defined($x); 131 } 132 133 # 134 # Remove prime from the context 135 # 136 sub Disable { 137 my $self = shift; my $context = shift || main::Context(); 138 $context->operators->remove("'"); 139 } 140 141 ########################################## 142 # 143 # Prime operator is a subclass of the unary operator class 144 # 145 package parser::Prime::UOP::prime; 146 our @ISA = ('Parser::UOP'); 147 148 # 149 # Do a typecheck on the operand 150 # 151 sub _check { 152 my $self = shift; 153 return if $self->checkInfinite || $self->checkString || 154 $self->checkList || $self->checkNumber; 155 $self->{type} = {%{$self->{op}->typeRef}}; 156 } 157 158 # 159 # A hack to prevent double-primes from inserting parentheses 160 # in string and TeX output (change the precedence to hide it) 161 # 162 sub string { 163 my ($self,$precedence,$showparens,$position,$outerRight) = @_; 164 my $uop = $self->{def}; $precedence -= .01 if $uop->{precedence} == $precedence; 165 return $self->SUPER::string($precedence,$showparens,$position,$outerRight); 166 } 167 sub TeX { 168 my ($self,$precedence,$showparens,$position,$outerRight) = @_; 169 my $uop = $self->{def}; $precedence -= .01 if $uop->{precedence} == $precedence; 170 return $self->SUPER::TeX($precedence,$showparens,$position,$outerRight); 171 } 172 173 # 174 # Produce a perl version of the derivative 175 # 176 sub perl { 177 my $self = shift; 178 return $self->{op}->D($self->getVar)->perl; 179 } 180 181 # 182 # Evaluate the derivative 183 # 184 sub eval { 185 my $self = shift; 186 return $self->{op}->D($self->getVar)->eval; 187 } 188 189 # 190 # Reduce by replacing with derivative 191 # 192 sub reduce { 193 my $self = shift; 194 return $self unless $self->context->{reduction}{"(f)'"}; 195 return $self->{op}->D($self->getVar); 196 } 197 198 sub getVar { 199 my $self = shift; 200 return $self->context->flag("prime_variable") || 201 (keys(%{$self->getVariables}))[0] || 202 (keys(%{$self->{equation}{variables}}))[0] || 'x'; 203 } 204 205 206 # 207 # Handle derivative by taking derivative of a prime by taking 208 # derivative of the prime's value (which is itself a derivative) 209 # 210 sub D { 211 my $self = shift; my $x = shift; 212 return $self->{op}->D($x)->D($x); 213 } 214 215 1; 216

aubreyja at gmail dot com | ViewVC Help |

Powered by ViewVC 1.0.9 |