[system] / trunk / pg / macros / parserFormulaUpToConstant.pl Repository: Repository Listing bbplugincoursesdistsnplrochestersystemwww

# Diff of /trunk/pg/macros/parserFormulaUpToConstant.pl

Revision 5440 Revision 5551
2
3parserFormulaUpToConstant.pl - implements formulas "plus a constant".
4
6
7This file implements the FormulaUpToConstant object, which is
8a formula that is only unique up to a constant (i.e., this is
9an anti-derivative). Students must include the "+C" as part of
10their answers, but they can use any (single-letter) constant that
11they want, and it doesn't have to be the one the professor used.
12
13To use FormulaWithConstat objects, load this macro file at the
14top of your problem:
15
17
18then create a formula with constant as follows:
19
20 \$f = FormulaUpToConstant("sin(x)+C");
21
22Note that the C should NOT already be a variable in the Context;
23the FormulaUpToConstant object will handle adding it in for
24you. If you don't include a constant in your formula (i.e., if
25all the variables that you used are already in your Context,
26then the FormulaUpToConstant object will add "+C" for you.
27
28The FormulaUpToConstant should work like any normal Formula,
29and in particular, you use \$f->cmp to get its answer checker.
30
31 ANS(\$f->cmp);
32
33Note that the FormulaUpToConstant object creates its only private
34copy of the current Context (so that it can add variables without
35affecting the rest of the problem). You should not notice this
36in general, but if you need to access that context, use \$f->{context}.
37E.g.
38
39 Context(\$f->{context});
40
41would make the current context the one being used by the
42FormulaUpToConstant, while
43
44 \$f->{context}->variables->names
45
46would return a list of the variables in the private context.
47
48To get the name of the constant in use in the formula,
49use
50
51 \$f->constant.
52
53If you combine a FormulaUpToConstant with other formulas,
54the result will be a new FormulaUpToConstant object, with
55a new Context, and potentially a new + C added to it. This
56is likely not what you want. Instead, you should convert
57back to a Formula first, then combine with other objects,
58then convert back to a FormulaUpToConstant, if necessary.
59To do this, use the removeConstant() method:
60
61 \$f = FormulaUpToConstant("sin(x)+C");
62 \$g = Formula("cos(x)");
63 \$h = \$f->removeConstant + \$g; # \$h will be "sin(x)+cos(x)"
64 \$h = FormulaUpToConstant(\$h); # \$h will be "sin(x)+cos(x)+C"
65
66The answer evaluator by default will give "helpful" messages
67to the student when the "+ C" is left out. You can turn off
68these messages using the showHints option to the cmp() method:
69
70 ANS(\$f->cmp(showHints => 0));
71
72One of the hints is about whether the student's answer is linear
73in the arbitrary constant. This test requires differentiating
74the student answer. Since there are times when that could be
75problematic, you can disable that test via the showLinearityHints
76flag. (Note: setting showHints to 0 also disables these hints.)
77
78 ANS(\$f->cmp(showLinearityHints => 0));
79
80=cut
81
2 83
3sub _parserFormulaUpToConstant_init {FormulaUpToConstant::Init()} 84sub _parserFormulaUpToConstant_init {FormulaUpToConstant::Init()}
4
6
7 ######################################################################
8 #
9 # This file implements the FormulaUpToConstant object, which is
10 # a formula that is only unique up to a constant (i.e., this is
11 # an anti-derivative). Students must include the "+C" as part of
12 # their answers, but they can use any (single-letter) constant that
13 # they want, and it doesn't have to be the one the professor used.
14 #
15 # To use FormulaWithConstat objects, load this macro file at the
16 # top of your problem:
17 #
19 #
20 # then create a formula with constant as follows:
21 #
22 # \$f = FormulaUpToConstant("sin(x)+C");
23 #
24 # Note that the C should NOT already be a variable in the Context;
25 # the FormulaUpToConstant object will handle adding it in for
26 # you. If you don't include a constant in your formula (i.e., if
27 # all the variables that you used are already in your Context,
28 # then the FormulaUpToConstant object will add "+C" for you.
29 #
30 # The FormulaUpToConstant should work like any normal Formula,
31 # and in particular, you use \$f->cmp to get its answer checker.
32 #
33 # ANS(\$f->cmp);
34 #
35 # Note that the FormulaUpToConstant object creates its only private
36 # copy of the current Context (so that it can add variables without
37 # affecting the rest of the problem). You should not notice this
38 # in general, but if you need to access that context, use \$f->{context}.
39 # E.g.
40 #
41 # Context(\$f->{context});
42 #
43 # would make the current context the one being used by the
44 # FormulaUpToConstant, while
45 #
46 # \$f->{context}->variables->names
47 #
48 # would return a list of the variables in the private context.
49 #
50 # To get the name of the constant in use in the formula,
51 # use
52 #
53 # \$f->constant.
54 #
55 # If you combine a FormulaUpToConstant with other formulas,
56 # the result will be a new FormulaUpToConstant object, with
57 # a new Context, and potentially a new + C added to it. This
58 # is likely not what you want. Instead, you should convert
59 # back to a Formula first, then combine with other objects,
60 # then convert back to a FormulaUpToConstant, if necessary.
61 # To do this, use the removeConstant() method:
62 #
63 # \$f = FormulaUpToConstant("sin(x)+C");
64 # \$g = Formula("cos(x)");
65 # \$h = \$f->removeConstant + \$g; # \$h will be "sin(x)+cos(x)"
66 # \$h = FormulaUpToConstant(\$h); # \$h will be "sin(x)+cos(x)+C"
67 #
68 # The answer evaluator by default will give "helpful" messages
69 # to the student when the "+ C" is left out. You can turn off
70 # these messages using the showHints option to the cmp() method:
71 #
72 # ANS(\$f->cmp(showHints => 0));
73 #
74 # One of the hints is about whether the student's answer is linear
75 # in the arbitrary constant. This test requires differentiating
76 # the student answer. Since there are times when that could be
77 # problematic, you can disable that test via the showLinearityHints
78 # flag. (Note: setting showHints to 0 also disables these hints.)
79 #
80 # ANS(\$f->cmp(showLinearityHints => 0));
81 #
82 ######################################################################
83
84=cut
85 85
86package FormulaUpToConstant; 86package FormulaUpToConstant;
87@ISA = ('Value::Formula'); 87@ISA = ('Value::Formula');
88 88
89sub Init { 89sub Init {
120 # 120 #
121 my \$n = \$f->D(\$f->{constant}); 121 my \$n = \$f->D(\$f->{constant});
122 Value->Error("Your formula isn't linear in the arbitrary constant '%s'",\$f->{constant}) 122 Value->Error("Your formula isn't linear in the arbitrary constant '%s'",\$f->{constant})
123 unless \$n->isConstant; 123 unless \$n->isConstant;
124 # 124 #
125 # Make a version with an adaptive parameter for use in the 125 # Make a version with adaptive parameters for use in the
126 # comparison later on. We could like n0*C, but already have \$n 126 # comparison later on. We could like n0*C, but already have \$n
127 # copies of C, so remove them. That way, n0 will be 0 when there 127 # copies of C, so remove them. That way, n0 will be 0 when there
128 # are no C's in the student answer during the adaptive comparison. 128 # are no C's in the student answer during the adaptive comparison.
129 # (Again, should really check that n0 is not in use already) 129 # (Again, should really check that n0 is not in use already)
130 # 130 #
131 my \$n0 = \$context->variables->get("n0"); 131 my \$n00 = \$context->variables->get("n00");
132 \$context->variables->add(n0=>'Parameter') unless \$n0 and \$n0->{parameter}; 132 \$context->variables->add(n00=>'Parameter') unless \$n00 and \$n00->{parameter};
133 my \$n01 = \$context->variables->get("n01");
134 \$context->variables->add(n01=>'Parameter') unless \$n01 and \$n01->{parameter};
133 \$f->{adapt} = \$f + "(n0-\$n)\$f->{constant}"; 135 \$f->{adapt} = \$f + "(n00-\$n)\$f->{constant} + n01";
134 return bless \$f, \$class; 136 return bless \$f, \$class;
135} 137}
136 138
137################################################## 139##################################################
138# 140#
160 return -1 unless \$l->{adapt} == \$r; 162 return -1 unless \$l->{adapt} == \$r;
161 # 163 #
162 # Check that n0 is non-zero (i.e., there is a multiple of C in the student answer) 164 # Check that n0 is non-zero (i.e., there is a multiple of C in the student answer)
163 # (remember: return value of 0 is equal, and non-zero is unequal) 165 # (remember: return value of 0 is equal, and non-zero is unequal)
164 # 166 #
165 return abs(\$context->variables->get("n0")->{value}) < \$context->flag("zeroLevelTol"); 167 return abs(\$context->variables->get("n00")->{value}) < \$context->flag("zeroLevelTol");
166} 168}
167 169
168################################################## 170##################################################
169# 171#
170# Here we override part of the answer comparison 172# Here we override part of the answer comparison
187 return unless \$ans->{score} == 0 && !\$ans->{isPreview}; 189 return unless \$ans->{score} == 0 && !\$ans->{isPreview};
188 return if \$ans->{ans_message} || !\$self->getFlag("showHints"); 190 return if \$ans->{ans_message} || !\$self->getFlag("showHints");
189 my \$student = \$ans->{student_value}; 191 my \$student = \$ans->{student_value};
190 my \$result = \$ans->{correct_value} <=> \$student; # compare encodes the reason in the result 192 my \$result = \$ans->{correct_value} <=> \$student; # compare encodes the reason in the result
191 \$self->cmp_Error(\$ans,"Note: there is always more than one posibility") if \$result == 2 || \$result == 3; 193 \$self->cmp_Error(\$ans,"Note: there is always more than one posibility") if \$result == 2 || \$result == 3;
194 if (\$result == 3) {
195 my \$context = \$self->context;
196 \$context->flags->set(no_parameters=>0);
198 \$result = 1 if \$self->removeConstant+"n01+n00x00" == \$student+"x00"; # must use both parameters
199 \$context->variables->remove('x00');
200 \$context->flags->set(no_parameters=>1);
201 }
192 \$self->cmp_Error(\$ans,"Your answer is not the most general solution") 202 \$self->cmp_Error(\$ans,"Your answer is not the most general solution") if \$result == 1;
193 if \$result == 1 || (\$result == 3 && \$self->removeConstant == \$student);
194 \$self->cmp_Error(\$ans,"Your formula should be linear in the constant '\$student->{constant}'") 203 \$self->cmp_Error(\$ans,"Your formula should be linear in the constant '\$student->{constant}'")
195 if \$result == -1 && \$self->getFlag("showLinearityHints") && !\$student->D(\$student->{constant})->isConstant; 204 if \$result == -1 && \$self->getFlag("showLinearityHints") && !\$student->D(\$student->{constant})->isConstant;
196} 205}
197 206
198################################################## 207##################################################

Legend:
 Removed from v.5440 changed lines Added in v.5551

 aubreyja at gmail dot com ViewVC Help Powered by ViewVC 1.0.9