[system] / trunk / pg / macros / PGmorematrixmacros.pl Repository:
ViewVC logotype

Annotation of /trunk/pg/macros/PGmorematrixmacros.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1237 - (view) (download) (as text)

1 : lr003k 1123 #!/usr/local/bin/webwork-perl
2 : gage 1064
3 :     BEGIN{
4 :     be_strict();
5 :     }
6 :    
7 :     sub _PGmorematrixmacros_init{}
8 :    
9 :     sub random_inv_matrix { ## Builds and returns a random invertible \$row by \$col matrix.
10 :    
11 :     warn "Usage: \$new_matrix = random_inv_matrix(\$rows,\$cols)"
12 :     if (@_ != 2);
13 :     my $A = new Matrix($_[0],$_[1]);
14 :     my $A_lr = new Matrix($_[0],$_[1]);
15 :     my $det = 0;
16 :     my $safety=0;
17 :     while ($det == 0 and $safety < 6) {
18 :     foreach my $i (1..$_[0]) {
19 :     foreach my $j (1..$_[1]) {
20 :     $A->assign($i,$j,random(-9,9,1) );
21 :     }
22 :     }
23 :     $A_lr = $A->decompose_LR();
24 :     $det = $A_lr->det_LR();
25 :     }
26 :     return $A;
27 :     }
28 :    
29 :     sub swap_rows{
30 :    
31 :     warn "Usage: \$new_matrix = swap_rows(\$matrix,\$row1,\$row2);"
32 :     if (@_ != 3);
33 :     my $matrix = $_[0];
34 :     my ($i,$j) = ($_[1],$_[2]);
35 :     warn "Error: Rows to be swapped must exist!"
36 :     if ($i>@$matrix or $j >@$matrix);
37 :     warn "Warning: Swapping the same row is pointless"
38 :     if ($i==$j);
39 :     my $cols = @{$matrix->[0]};
40 :     my $B = new Matrix(@$matrix,$cols);
41 :     foreach my $k (1..$cols){
42 :     $B->assign($i,$k,element $matrix($j,$k));
43 :     $B->assign($j,$k,element $matrix($i,$k));
44 :     }
45 :     return $B;
46 :     }
47 :    
48 :     sub row_mult{
49 :    
50 :     warn "Usage: \$new_matrix = row_mult(\$matrix,\$scalar,\$row);"
51 :     if (@_ != 3);
52 :     my $matrix = $_[0];
53 :     my ($scalar,$row) = ($_[1],$_[2]);
54 :     warn "Undefined row multiplication"
55 :     if ($row > @$matrix);
56 :     my $B = new Matrix(@$matrix,@{$matrix->[0]});
57 :     foreach my $j (1..@{$matrix->[0]}) {
58 :     $B->assign($row,$j,$scalar*element $matrix($row,$j));
59 :     }
60 :     return $B;
61 :     }
62 :    
63 :     sub linear_combo{
64 :    
65 :     warn "Usage: \$new_matrix = linear_combo(\$matrix,\$scalar,\$row1,\$row2);"
66 :     if (@_ != 4);
67 :     my $matrix = $_[0];
68 :     my ($scalar,$row1,$row2) = ($_[1],$_[2],$_[3]);
69 :     warn "Undefined row in multiplication"
70 :     if ($row1>@$matrix or $row2>@$matrix);
71 :     warn "Warning: Using the same row"
72 :     if ($row1==$row2);
73 :     my $B = new Matrix(@$matrix,@{$matrix->[0]});
74 :     foreach my $j (1..@$matrix) {
75 :     my ($t1,$t2) = (element $matrix($row1,$j),element $matrix($row2,$j));
76 :     $B->assign($row2,$j,$scalar*$t1+$t2);
77 :     }
78 :     return $B;
79 :     }
80 :    
81 : gage 1071 =head3 basis_cmp()
82 : gage 1064
83 : gage 1071 Compares a list of vectors by finding the change of coordinate matrix
84 :     from the Prof's vectors to the students, and then taking the determinant of
85 :     that to determine the existence of the change of coordinate matrix going the
86 :     other way.
87 :    
88 :     ANS( basis_cmp( vectors_as_array_ref_in_array_ref, options_hash ) );
89 :    
90 :     1. a reference to an array of correct vectors
91 :     2. a hash with the following keys (all optional):
92 :     mode -- 'basis' (default) (only a basis allowed)
93 :     'orthogonal' (only an orthogonal basis is allowed)
94 :     'unit' (only unit vectors in the basis allowed)
95 :     'orthonormal' (only orthogonal unit vectors in basis allowed)
96 :     zeroLevelTol -- absolute tolerance to allow when answer is close
97 :     to zero
98 :    
99 :     debug -- if set to 1, provides verbose listing of
100 :     hash entries throughout fliters.
101 :    
102 :     help -- 'none' (default) (is quiet on all errors)
103 :     'dim' (Tells student if wrong number of vectors are entered)
104 :     'length' (Tells student if there is a vector of the wrong length)
105 :     'orthogonal' (Tells student if their vectors are not orthogonal)
106 :     (This is only in orthogonal mode)
107 :     'unit' (Tells student if there is a vector not of unit length)
108 :     (This is only in unit mode)
109 :     'orthonormal' (Gives errors from orthogonal and orthonormal)
110 :     (This is only in orthonormal mode)
111 :     'verbose' (Gives all the above answer messages)
112 :    
113 :     Returns an answer evaluator.
114 :    
115 :     EXAMPLES:
116 :    
117 :     basis_cmp([[1,0,0],[0,1,0],[0,0,1]])
118 :     -- correct answer is any basis for R^3.
119 :     basis_cmp([1,0,2,0],[0,1,0,0], 'mode'=>orthonormal )
120 :     -- correct answer is any orthonormal basis
121 :     for this space such as:
122 :     [1/sqrt(3),0,2/sqrt(3),0],[0,1,0,0]
123 :    
124 :     =cut
125 :    
126 :    
127 :     sub basis_cmp {
128 :     my $correctAnswer = shift;
129 :     my %opt = @_;
130 :    
131 :     set_default_options( \%opt,
132 :     'zeroLevelTol' => $main::functZeroLevelTolDefault,
133 :     'debug' => 0,
134 :     'mode' => 'basis',
135 :     'help' => 'none',
136 :     );
137 :    
138 :     # produce answer evaluator
139 :     BASIS_CMP(
140 :     'correct_ans' => $correctAnswer,
141 :     'zeroLevelTol' => $opt{'zeroLevelTol'},
142 :     'debug' => $opt{'debug'},
143 :     'mode' => $opt{'mode'},
144 :     'help' => $opt{'help'},
145 :     );
146 :     }
147 :    
148 :     =head BASIS_CMP
149 :    
150 :     Made to keep the same format as num_cmp and fun_cmp.
151 :    
152 :     =cut
153 :    
154 :     sub BASIS_CMP {
155 :     my %mat_params = @_;
156 :     my $zeroLevelTol = $mat_params{'zeroLevelTol'};
157 :    
158 :     # Check that everything is defined:
159 :     $mat_params{debug} = 0 unless defined($mat_params{debug});
160 :     $zeroLevelTol = $main::functZeroLevelTolDefault unless defined $zeroLevelTol;
161 :     $mat_params{'zeroLevelTol'} = $zeroLevelTol;
162 :    
163 :     ## This is where the correct answer should be checked someday.
164 :     my $matrix = Matrix->new_from_col_vecs($mat_params{'correct_ans'});
165 :    
166 :     #construct the answer evaluator
167 :     my $answer_evaluator = new AnswerEvaluator;
168 :    
169 :     $answer_evaluator->{debug} = $mat_params{debug};
170 :    
171 :     $answer_evaluator->ans_hash( correct_ans => pretty_print($mat_params{correct_ans}),
172 :     rm_correct_ans => $matrix,
173 :     zeroLevelTol => $mat_params{zeroLevelTol},
174 :     debug => $mat_params{debug},
175 :     mode => $mat_params{mode},
176 :     help => $mat_params{help},
177 :     );
178 :    
179 :     $answer_evaluator->install_pre_filter(sub {my $rh_ans = shift;
180 :     $rh_ans->{student_ans} =~ s/\s+//g; # remove all whitespace
181 :     $rh_ans;
182 :     });
183 :    
184 :     $answer_evaluator->install_pre_filter(\&math_constants);
185 : lr003k 1123 $answer_evaluator->install_pre_filter(sub{my $rh_ans = shift; my @options = @_;
186 :     if( $rh_ans->{ans_label} =~ /ArRaY/ ){
187 :     $rh_ans = ans_array_filter($rh_ans,@options);
188 :     my @student_array = @{$rh_ans->{ra_student_ans}};
189 :     my @array = ();
190 :     for( my $i = 0; $i < scalar(@student_array) ; $i ++ )
191 :     {
192 :     push( @array, Matrix->new_from_array_ref($student_array[$i]));
193 :     }
194 :     $rh_ans->{ra_student_ans} = \@array;
195 :     $rh_ans;
196 :     }else{
197 :     vec_list_string($rh_ans,@options);
198 :     }
199 :    
200 :     });#ra_student_ans is now the students answer as an array of vectors
201 : gage 1071 # anonymous subroutine to check dimension and length of the student vectors
202 :     # if either is wrong, the answer is wrong.
203 :     $answer_evaluator->install_pre_filter(sub{
204 :     my $rh_ans = shift;
205 :     my $length = $rh_ans->{rm_correct_ans}->[1];
206 :     my $dim = $rh_ans->{rm_correct_ans}->[2];
207 :     if( $dim != scalar(@{$rh_ans->{ra_student_ans}}))
208 :     {
209 :    
210 :     $rh_ans->{score} = 0;
211 :     if( $rh_ans->{help} =~ /dim|verbose/ )
212 :     {
213 :     $rh_ans->throw_error('EVAL','You have entered the wrong number of vectors.');
214 :     }else{
215 :     $rh_ans->throw_error('EVAL');
216 :     }
217 :     }
218 :     for( my $i = 0; $i < scalar( @{$rh_ans->{ra_student_ans} }) ; $i++ )
219 :     {
220 :     if( $length != $rh_ans->{ra_student_ans}->[$i]->[1])
221 :     {
222 :     $rh_ans->{score} = 0;
223 :     if( $rh_ans->{help} =~ /length|verbose/ )
224 :     {
225 :     $rh_ans->throw_error('EVAL','You have entered vector(s) of the wrong length.');
226 :     }else{
227 :     $rh_ans->throw_error('EVAL');
228 :     }
229 :     }
230 :     }
231 :     $rh_ans;
232 :     });
233 :     # Install prefilter for various modes
234 :     if( $mat_params{mode} ne 'basis' )
235 :     {
236 :     if( $mat_params{mode} =~ /orthogonal|orthonormal/ )
237 :     {
238 :     $answer_evaluator->install_pre_filter(sub{
239 :     my $rh_ans = shift;
240 :     my @vecs = @{$rh_ans->{ra_student_ans}};
241 :     my ($i,$j) = (0,0);
242 :     my $num = scalar(@vecs);
243 :     my $length = $vecs[0]->[1];
244 :    
245 :     for( ; $i < $num ; $i ++ )
246 :     {
247 :     for( $j = $i+1; $j < $num ; $j++ )
248 :     {
249 :     my $sum = 0;
250 :     my $k = 0;
251 :    
252 :     for( ; $k < $length; $k++ ) {
253 :     $sum += $vecs[$i]->[0][$k][0]*$vecs[$j]->[0][$k][0];
254 :     }
255 :    
256 :     if( $sum > $mat_params{zeroLevelTol} )
257 :     {
258 :     $rh_ans->{score} = 0;
259 :     if( $rh_ans->{help} =~ /orthogonal|orthonormal|verbose/ )
260 :     {
261 :     $rh_ans->throw_error('EVAL','You have entered vectors which are not orthogonal. ');
262 :     }else{
263 :     $rh_ans->throw_error('EVAL');
264 :     }
265 :     }
266 :     }
267 :     }
268 :    
269 :    
270 :     $rh_ans;
271 :     });
272 :     }
273 :    
274 :     if( $mat_params{mode} =~ /unit|orthonormal/ )
275 :     {
276 :     $answer_evaluator->install_pre_filter(sub{
277 :     my $rh_ans = shift;
278 :     my @vecs = @{$rh_ans->{ra_student_ans}};
279 :     my $i = 0;
280 :     my $num = scalar(@vecs);
281 :     my $length = $vecs[0]->[1];
282 :    
283 :     for( ; $i < $num ; $i ++ )
284 :     {
285 :     my $sum = 0;
286 :     my $k = 0;
287 :    
288 :     for( ; $k < $length; $k++ ) {
289 :     $sum += $vecs[$i]->[0][$k][0]*$vecs[$i]->[0][$k][0];
290 :     }
291 :     if( abs(sqrt($sum) - 1) > $mat_params{zeroLevelTol} )
292 :     {
293 :     $rh_ans->{score} = 0;
294 :    
295 :     if( $rh_ans->{help} =~ /unit|orthonormal|verbose/ )
296 :     {
297 :     $rh_ans->throw_error('EVAL','You have entered vector(s) which are not of unit length.');
298 :     }else{
299 :     $rh_ans->throw_error('EVAL');
300 :     }
301 :     }
302 :     }
303 :    
304 :    
305 :     $rh_ans;
306 :     });
307 :    
308 :     }
309 :     }
310 :     $answer_evaluator->install_evaluator(\&compare_basis, %mat_params);
311 :     $answer_evaluator->install_post_filter(
312 :     sub {my $rh_ans = shift;
313 :     if ($rh_ans->catch_error('SYNTAX') ) {
314 :     $rh_ans->{ans_message} = $rh_ans->{error_message};
315 :     $rh_ans->clear_error('SYNTAX');
316 :     }
317 :     if ($rh_ans->catch_error('EVAL') ) {
318 :     $rh_ans->{ans_message} = $rh_ans->{error_message};
319 :     $rh_ans->clear_error('EVAL');
320 :     }
321 :     $rh_ans;
322 :     }
323 :     );
324 :     $answer_evaluator;
325 :     }
326 :    
327 :     =head4 compare_basis
328 :    
329 :     compare_basis( $ans_hash, %options);
330 :    
331 :     {ra_student_ans}, # a reference to the array of students answer vectors
332 :     {rm_correct_ans}, # a reference to the correct answer matrix
333 :     %options
334 :     )
335 :    
336 :     =cut
337 :    
338 :     sub compare_basis {
339 :     my ($rh_ans, %options) = @_;
340 :     my @ch_coord;
341 :     my @vecs = @{$rh_ans->{ra_student_ans}};
342 :    
343 :     # A lot of the follosing code was taken from Matrix::proj_coeff
344 :     # calling this method recursively would be a waste of time since
345 :     # the prof's matrix never changes and solve_LR is an expensive
346 :     # operation. This way it is only done once.
347 :     my $matrix = $rh_ans->{rm_correct_ans};
348 :     my ($dim,$x_vector, $base_matrix);
349 :     my $errors = undef;
350 :     my $lin_space_tr= ~ $matrix;
351 :     $matrix = $lin_space_tr * $matrix;
352 :     my $matrix_lr = $matrix->decompose_LR();
353 :    
354 :     #finds the coefficient vectors for each of the students vectors
355 :     for( my $i = 0; $i < scalar(@{$rh_ans->{ra_student_ans}}) ; $i++ )
356 :     {
357 :    
358 :     $vecs[$i] = $lin_space_tr*$vecs[$i];
359 :     ($dim,$x_vector, $base_matrix) = $matrix_lr->solve_LR($vecs[$i]);
360 :     push( @ch_coord, $x_vector );
361 :     $errors = "A unique adapted answer could not be determined. Possibly the parameters have coefficient zero.<br> dim = $dim base_matrix is $base_matrix\n" if $dim; # only print if the dim is not zero.
362 :     }
363 :    
364 :     if( defined($errors))
365 :     {
366 :     $rh_ans->throw_error('EVAL', $errors) ;
367 :     }else{
368 :     my $ch_coord_mat = Matrix->new_from_col_vecs(\@ch_coord);#creates change of coordinate matrix
369 :     #existence of this matrix implies that
370 :     #the all of the students answers are a
371 :     #linear combo of the prof's
372 :     $ch_coord_mat = $ch_coord_mat->decompose_LR();
373 :    
374 : lr003k 1161 if( abs($ch_coord_mat->det_LR()) > $options{zeroLevelTol} )# if the det of the change of coordinate matrix is
375 : gage 1071 # non-zero, this implies the existence of an inverse
376 :     # which implies all of the prof's vectors are a linear
377 :     # combo of the students vectors, showing containment
378 :     # both ways.
379 :     {
380 :     # I think sometimes if the students space has the same dimension as the profs space it
381 :     # will get projected into the profs space even if it isn't a basis for that space.
382 :     # this just checks that the prof's matrix times the change of coordinate matrix is actually
383 :     #the students matrix
384 :     if( abs(Matrix->new_from_col_vecs(\@{$rh_ans->{ra_student_ans}}) - ($rh_ans->{rm_correct_ans})*(Matrix->new_from_col_vecs(\@ch_coord))) < $options{zeroLevelTol} )
385 :     {
386 :     $rh_ans->{score} = 1;
387 :     }else{
388 :     $rh_ans->{score} = 0;
389 :     }
390 :     }
391 :     else{
392 :     $rh_ans->{score}=0;
393 :     }
394 :     }
395 :     $rh_ans;
396 :    
397 :     }
398 :    
399 :    
400 :     =head 2 vec_list_string
401 :    
402 :     This is a check_syntax type method (in fact I borrowed some of that method's code) for vector input.
403 :     The student needs to enter vectors like: [1,0,0],[1,2,3],[0,9/sqrt(10),1/sqrt(10)]
404 :     Each entry can contain functions and operations and the usual math constants (pi and e).
405 :     The vectors, however can not be added or multiplied or scalar multiplied by the student.
406 :     Most errors are handled well. Any error in an entry is caught by the PG_answer_eval like it is in num_cmp or fun_cmp.
407 :     Right now the method basically ignores every thing outside the vectors. Also, an unmatched open parenthesis is caught,
408 :     but a unmatched close parenthesis ends the vector, and since everything outside is ignored, no error is sent (other than the
409 :     later when the length of the vectors is checked.
410 :     In the end, the method returns an array of Matrix objects.
411 :    
412 :    
413 :     =cut
414 :    
415 :     sub vec_list_string{
416 :     my $rh_ans = shift;
417 :     my %options = @_;
418 :     my $i;
419 :     my $entry = "";
420 :     my $char;
421 :     my @paren_stack;
422 :     my $length = length($rh_ans->{student_ans});
423 :     my @temp;
424 :     my $j = 0;
425 :     my @answers;
426 :     my $paren;
427 :     my $display_ans;
428 :    
429 :     for( $i = 0; $i < $length ; $i++ )
430 :     {
431 :     $char = substr($rh_ans->{student_ans},$i,1);
432 :    
433 :     if( $char =~ /\(|\[|\{/ ){
434 :     push( @paren_stack, $char )
435 :     }
436 :    
437 :     if( !( $char =~ /\(|\[|\{/ && scalar(@paren_stack) == 1 ) )
438 :     {
439 :     if( $char !~ /,|\)|\]|\}/ ){
440 :     $entry .= $char;
441 :     }else{
442 :     if( $char =~ /,/ || ( $char =~ /\)|\]|\}/ && scalar(@paren_stack) == 1 ) )
443 :     {
444 :     if( length($entry) == 0 ){
445 :     if( $char !~ /,/ ){
446 :     $rh_ans->throw_error('EVAL','There is a syntax error in your answer');
447 :     }else{
448 :     $rh_ans->{preview_text_string} .= ",";
449 :     $rh_ans->{preview_latex_string} .= ",";
450 :     $display_ans .= ",";
451 :     }
452 :     }else{
453 :    
454 :     # This parser code was origianally taken from PGanswermacros::check_syntax
455 :     # but parts of it needed to be slighty modified for this context
456 :     my $parser = new AlgParserWithImplicitExpand;
457 :     my $ret = $parser -> parse($entry); #for use with loops
458 :    
459 :     if ( ref($ret) ) { ## parsed successfully
460 :     $parser -> tostring();
461 :     $parser -> normalize();
462 :     $entry = $parser -> tostring();
463 :     $rh_ans->{preview_text_string} .= $entry.",";
464 :     $rh_ans->{preview_latex_string} .= $parser -> tolatex().",";
465 :    
466 :     } else { ## error in parsing
467 :    
468 :     $rh_ans->{'student_ans'} = 'syntax error:'.$display_ans. $parser->{htmlerror},
469 :     $rh_ans->{'ans_message'} = $display_ans.$parser -> {error_msg},
470 :     $rh_ans->{'preview_text_string'} = '',
471 :     $rh_ans->{'preview_latex_string'} = '',
472 :     $rh_ans->throw_error('SYNTAX', 'syntax error in answer:'.$display_ans.$parser->{htmlerror} . "$main::BR" .$parser -> {error_msg}.".$main::BR");
473 :     }
474 :    
475 :     my ($inVal,$PG_eval_errors,$PG_full_error_report) = PG_answer_eval($entry);
476 :    
477 :     if ($PG_eval_errors) {
478 :     $rh_ans->throw_error('EVAL','There is a syntax error in your answer.') ;
479 :     $rh_ans->{ans_message} = clean_up_error_msg($PG_eval_errors);
480 :     last;
481 :     } else {
482 :     $entry = prfmt($inVal,$options{format});
483 :     $display_ans .= $entry.",";
484 :     push(@temp , $entry);
485 :     }
486 :    
487 :     if( $char =~ /\)|\]|\}/ && scalar(@paren_stack) == 1)
488 :     {
489 :     pop @paren_stack;
490 :     chop($rh_ans->{preview_text_string});
491 :     chop($rh_ans->{preview_latex_string});
492 :     chop($display_ans);
493 :     $rh_ans->{preview_text_string} .= "]";
494 :     $rh_ans->{preview_latex_string} .= "]";
495 :     $display_ans .= "]";
496 :     if( scalar(@temp) > 0 )
497 :     {
498 :     push( @answers,Matrix->new_from_col_vecs([\@temp]));
499 :     while(scalar(@temp) > 0 ){
500 :     pop @temp;
501 :     }
502 :     }else{
503 :     $rh_ans->throw_error('EVAL','There is a syntax error in your answer.');
504 :     }
505 :     }
506 :     }
507 :     $entry = "";
508 :     }else{
509 :     $paren = pop @paren_stack;
510 :     if( scalar(@paren_stack) > 0 ){
511 :     #this uses ASCII to check if the parens match up
512 :     # in ASCII ord ( = 40 , ord ) = 41 , ord [ = 91 ,
513 :     # ord ] = 93 , ord { = 123 , ord } = 125
514 :     if( (ord($char) - ord($paren) <= 2) ){
515 :     $entry = $entry . $char;
516 :     }else{
517 :     $rh_ans->throw_error('EVAL','There is a syntax error in your answer');
518 :     }
519 :     }
520 :     }
521 :     }
522 :     }else{
523 :     $rh_ans->{preview_text_string} .= "[";
524 :     $rh_ans->{preview_latex_string} .= "[";
525 :     $display_ans .= "[";
526 :     }
527 :     }
528 :     $rh_ans->{ra_student_ans} = \@answers;
529 :     $rh_ans->{student_ans} = $display_ans unless $rh_ans->{error_flag};
530 :     $rh_ans;
531 :     }
532 :    
533 : lr003k 1123 sub ans_array_filter{
534 :     my $rh_ans = shift;
535 :     my %options = @_;
536 :     $rh_ans->{ans_label} =~ /ArRaY(\d+)\[\d+,\d+,\d+\]/;
537 :     my $ans_num = $1;
538 :     my @keys = grep /ArRaY$ans_num/, keys(%{$main::inputs_ref});
539 :     my $key;
540 :     my @array = ();
541 : lr003k 1237 #my @latex = ();
542 : lr003k 1123 my ($i,$j,$k) = (0,0,0);
543 :    
544 :     #the keys aren't in order, so their info has to be put into the array before doing anything with it
545 :     foreach $key (@keys){
546 :     $key =~ /ArRaY\d+\[(\d+),(\d+),(\d+)\]/;
547 :     ($i,$j,$k) = ($1,$2,$3);
548 :     $array[$i][$j][$k] = ${$main::inputs_ref}{'ArRaY'.$ans_num.'['.$i.','.$j.','.$k.']'};
549 :     }
550 :    
551 :     my $display_ans = "";
552 :    
553 :     for( $i=0; $i < scalar(@array) ; $i ++ )
554 :     {
555 :     $display_ans .= " [";
556 :     $rh_ans->{preview_text_string} .= ' [';
557 :     $rh_ans->{preview_latex_string} .= ' [';
558 :     for( $j = 0; $j < scalar( @{$array[$i]} ) ; $j++ )
559 :     {
560 :     $display_ans .= " [";
561 :     $rh_ans->{preview_text_string} .= ' [';
562 :     $rh_ans->{preview_latex_string} .= ' [';
563 :     for( $k = 0; $k < scalar( @{$array[$i][$j]} ) ; $k ++ ){
564 :     my $entry = $array[$i][$j][$k];
565 :    
566 :     # This parser code was origianally taken from PGanswermacros::check_syntax
567 :     # but parts of it needed to be slighty modified for this context
568 :     my $parser = new AlgParserWithImplicitExpand;
569 :     my $ret = $parser -> parse($entry); #for use with loops
570 :    
571 :     if ( ref($ret) ) { ## parsed successfully
572 :     $parser -> tostring();
573 :     $parser -> normalize();
574 :     $entry = $parser -> tostring();
575 :     $rh_ans->{preview_text_string} .= $entry.",";
576 :     $rh_ans->{preview_latex_string} .= $parser -> tolatex().",";
577 : lr003k 1237 #$latex[$i][$j][$k] = "\\{".$parser -> tolatex()."\\}";
578 :    
579 : lr003k 1123 } else { ## error in parsing
580 :     $rh_ans->{'student_ans'} = 'syntax error:'.$display_ans. $parser->{htmlerror},
581 :     $rh_ans->{'ans_message'} = $display_ans.$parser -> {error_msg},
582 :     $rh_ans->{'preview_text_string'} = '',
583 :     $rh_ans->{'preview_latex_string'} = '',
584 :     $rh_ans->throw_error('SYNTAX', 'syntax error in answer:'.$display_ans.$parser->{htmlerror} . "$main::BR" .$parser -> {error_msg}.".$main::BR");
585 :     }
586 :    
587 :     my ($inVal,$PG_eval_errors,$PG_full_error_report) = PG_answer_eval($entry);
588 :     if ($PG_eval_errors) {
589 :     $rh_ans->throw_error('EVAL','There is a syntax error in your answer.') ;
590 :     $rh_ans->{ans_message} = clean_up_error_msg($PG_eval_errors);
591 :     last;
592 :     } else {
593 :     $entry = prfmt($inVal,$options{format});
594 :     $display_ans .= $entry.",";
595 :     $array[$i][$j][$k] = $entry;
596 :     }
597 :     }
598 :     chop($rh_ans->{preview_text_string});
599 :     chop($rh_ans->{preview_latex_string});
600 :     chop($display_ans);
601 :     $rh_ans->{preview_text_string} .= '] ,';
602 :     $rh_ans->{preview_latex_string} .= '] ,';
603 :     $display_ans .= '] ,';
604 :    
605 :     }
606 :     chop($rh_ans->{preview_text_string});
607 :     chop($rh_ans->{preview_latex_string});
608 :     chop($display_ans);
609 :     $rh_ans->{preview_text_string} .= '] ,';
610 :     $rh_ans->{preview_latex_string} .= '] ,';
611 :     $display_ans .= '] ,';
612 :     }
613 :     chop($rh_ans->{preview_text_string});
614 :     chop($rh_ans->{preview_latex_string});
615 :     chop($display_ans);
616 :    
617 : lr003k 1237 #for( $i = 0 ; $i < scalar( @latex ); $i++ ){
618 :     # $latex[$i] = display_matrix($latex[$i]);
619 :     #}
620 :     #$rh_ans->{preview_latex_string} = mbox(\@latex);
621 :     my @temp = ();
622 :     for( $i = 0 ; $i < scalar( @array ); $i++ ){
623 :     push @temp , display_matrix($array[$i], 'left'=>'.', 'right'=>'.');
624 :     push @temp , "," unless $i == scalar(@array) - 1;
625 :     }
626 :     $rh_ans->{student_ans} = mbox(\@temp);
627 : lr003k 1123 $rh_ans->{ra_student_ans} = \@array;
628 :    
629 :     $rh_ans;
630 :    
631 :     }
632 :    
633 : gage 1064 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9