| … | |
… | |
| 165 | |
165 | |
| 166 | #construct the answer evaluator |
166 | #construct the answer evaluator |
| 167 | my $answer_evaluator = new AnswerEvaluator; |
167 | my $answer_evaluator = new AnswerEvaluator; |
| 168 | |
168 | |
| 169 | $answer_evaluator->{debug} = $mat_params{debug}; |
169 | $answer_evaluator->{debug} = $mat_params{debug}; |
| 170 | |
|
|
| 171 | $answer_evaluator->ans_hash( correct_ans => pretty_print($mat_params{correct_ans}), |
170 | $answer_evaluator->ans_hash( correct_ans => pretty_print($mat_params{correct_ans}), |
| 172 | rm_correct_ans => $matrix, |
171 | rm_correct_ans => $matrix, |
| 173 | zeroLevelTol => $mat_params{zeroLevelTol}, |
172 | zeroLevelTol => $mat_params{zeroLevelTol}, |
| 174 | debug => $mat_params{debug}, |
173 | debug => $mat_params{debug}, |
| 175 | mode => $mat_params{mode}, |
174 | mode => $mat_params{mode}, |
| 176 | help => $mat_params{help}, |
175 | help => $mat_params{help}, |
| … | |
… | |
| 178 | |
177 | |
| 179 | $answer_evaluator->install_pre_filter(sub {my $rh_ans = shift; |
178 | $answer_evaluator->install_pre_filter(sub {my $rh_ans = shift; |
| 180 | $rh_ans->{student_ans} =~ s/\s+//g; # remove all whitespace |
179 | $rh_ans->{student_ans} =~ s/\s+//g; # remove all whitespace |
| 181 | $rh_ans; |
180 | $rh_ans; |
| 182 | }); |
181 | }); |
| 183 | |
|
|
| 184 | $answer_evaluator->install_pre_filter(\&math_constants); |
|
|
| 185 | $answer_evaluator->install_pre_filter(sub{my $rh_ans = shift; my @options = @_; |
182 | $answer_evaluator->install_pre_filter(sub{my $rh_ans = shift; my @options = @_; |
| 186 | if( $rh_ans->{ans_label} =~ /ArRaY/ ){ |
183 | if( $rh_ans->{ans_label} =~ /ArRaY/ ){ |
| 187 | $rh_ans = ans_array_filter($rh_ans,@options); |
184 | $rh_ans = ans_array_filter($rh_ans,@options); |
| 188 | my @student_array = @{$rh_ans->{ra_student_ans}}; |
185 | my @student_array = @{$rh_ans->{ra_student_ans}}; |
| 189 | my @array = (); |
186 | my @array = (); |
| … | |
… | |
| 192 | push( @array, Matrix->new_from_array_ref($student_array[$i])); |
189 | push( @array, Matrix->new_from_array_ref($student_array[$i])); |
| 193 | } |
190 | } |
| 194 | $rh_ans->{ra_student_ans} = \@array; |
191 | $rh_ans->{ra_student_ans} = \@array; |
| 195 | $rh_ans; |
192 | $rh_ans; |
| 196 | }else{ |
193 | }else{ |
|
|
194 | $rh_ans->{student_ans} = math_constants($rh_ans->{student_ans}); |
| 197 | vec_list_string($rh_ans,@options); |
195 | vec_list_string($rh_ans,@options); |
| 198 | } |
196 | } |
| 199 | |
197 | |
| 200 | });#ra_student_ans is now the students answer as an array of vectors |
198 | });#ra_student_ans is now the students answer as an array of vectors |
| 201 | # anonymous subroutine to check dimension and length of the student vectors |
199 | # anonymous subroutine to check dimension and length of the student vectors |
| … | |
… | |
| 233 | # Install prefilter for various modes |
231 | # Install prefilter for various modes |
| 234 | if( $mat_params{mode} ne 'basis' ) |
232 | if( $mat_params{mode} ne 'basis' ) |
| 235 | { |
233 | { |
| 236 | if( $mat_params{mode} =~ /orthogonal|orthonormal/ ) |
234 | if( $mat_params{mode} =~ /orthogonal|orthonormal/ ) |
| 237 | { |
235 | { |
| 238 | $answer_evaluator->install_pre_filter(sub{ |
236 | $answer_evaluator->install_pre_filter(\&are_orthogonal_vecs); |
| 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 | } |
237 | } |
| 273 | |
238 | |
| 274 | if( $mat_params{mode} =~ /unit|orthonormal/ ) |
239 | if( $mat_params{mode} =~ /unit|orthonormal/ ) |
| 275 | { |
240 | { |
| 276 | $answer_evaluator->install_pre_filter(sub{ |
241 | $answer_evaluator->install_pre_filter(\&are_unit_vecs); |
| 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 | |
242 | |
| 308 | } |
243 | } |
| 309 | } |
244 | } |
| 310 | $answer_evaluator->install_evaluator(\&compare_basis, %mat_params); |
245 | $answer_evaluator->install_evaluator(\&compare_basis, %mat_params); |
| 311 | $answer_evaluator->install_post_filter( |
246 | $answer_evaluator->install_post_filter( |
| … | |
… | |
| 628 | |
563 | |
| 629 | $rh_ans; |
564 | $rh_ans; |
| 630 | |
565 | |
| 631 | } |
566 | } |
| 632 | |
567 | |
|
|
568 | |
|
|
569 | sub are_orthogonal_vecs{ |
|
|
570 | my ( $vec_ref,%opts ) = @_; |
|
|
571 | my @vecs = (); |
|
|
572 | if( ref($vec_ref) eq 'AnswerHash' ) |
|
|
573 | { |
|
|
574 | @vecs = @{$vec_ref->{ra_student_ans}}; |
|
|
575 | }else{ |
|
|
576 | @vecs = @{$vec_ref}; |
|
|
577 | } |
|
|
578 | |
|
|
579 | my ($i,$j) = (0,0); |
|
|
580 | |
|
|
581 | my $num = scalar(@vecs); |
|
|
582 | my $length = $vecs[0]->[1]; |
|
|
583 | |
|
|
584 | for( ; $i < $num ; $i ++ ) |
|
|
585 | { |
|
|
586 | for( $j = $i+1; $j < $num ; $j++ ) |
|
|
587 | { |
|
|
588 | my $sum = 0; |
|
|
589 | my $k = 0; |
|
|
590 | |
|
|
591 | for( ; $k < $length; $k++ ) { |
|
|
592 | $sum += $vecs[$i]->[0][$k][0]*$vecs[$j]->[0][$k][0]; |
|
|
593 | } |
|
|
594 | |
|
|
595 | if( $sum > $main::functZeroLevelTolDefault ) |
|
|
596 | { |
|
|
597 | if( ref( $vec_ref ) eq 'AnswerHash' ){ |
|
|
598 | $vec_ref->{score} = 0; |
|
|
599 | if( $opts{help} =~ /orthogonal|orthonormal|verbose/ ) |
|
|
600 | { |
|
|
601 | $vec_ref->throw_error('EVAL','You have entered vectors which are not orthogonal. '); |
|
|
602 | }else{ |
|
|
603 | $vec_ref->throw_error('EVAL'); |
|
|
604 | } |
|
|
605 | return $vec_ref; |
|
|
606 | }else{ |
|
|
607 | return 0; |
|
|
608 | } |
|
|
609 | } |
|
|
610 | } |
|
|
611 | } |
|
|
612 | if( ref( $vec_ref ) eq 'AnswerHash' ){ |
|
|
613 | $vec_ref->{score} = 1; |
|
|
614 | $vec_ref; |
|
|
615 | }else{ |
|
|
616 | 1; |
|
|
617 | } |
|
|
618 | } |
|
|
619 | |
|
|
620 | sub are_unit_vecs{ |
|
|
621 | my ( $vec_ref,%opts ) = @_; |
|
|
622 | my @vecs = (); |
|
|
623 | if( ref($vec_ref) eq 'AnswerHash' ) |
|
|
624 | { |
|
|
625 | @vecs = @{$vec_ref->{ra_student_ans}}; |
|
|
626 | }else{ |
|
|
627 | @vecs = @{$vec_ref}; |
|
|
628 | } |
|
|
629 | |
|
|
630 | my $i = 0; |
|
|
631 | my $num = scalar(@vecs); |
|
|
632 | my $length = $vecs[0]->[1]; |
|
|
633 | |
|
|
634 | for( ; $i < $num ; $i ++ ) |
|
|
635 | { |
|
|
636 | my $sum = 0; |
|
|
637 | my $k = 0; |
|
|
638 | |
|
|
639 | for( ; $k < $length; $k++ ) { |
|
|
640 | $sum += $vecs[$i]->[0][$k][0]*$vecs[$i]->[0][$k][0]; |
|
|
641 | } |
|
|
642 | if( abs(sqrt($sum) - 1) > $main::functZeroLevelTolDefault ) |
|
|
643 | { |
|
|
644 | if( ref( $vec_ref ) eq 'AnswerHash' ){ |
|
|
645 | $vec_ref->{score} = 0; |
|
|
646 | if( $opts{mode} =~ /unit|orthonormal|verbose/ ) |
|
|
647 | { |
|
|
648 | $vec_ref->throw_error('EVAL','You have entered vector(s) which are not of unit length.'); |
|
|
649 | }else{ |
|
|
650 | $vec_ref->throw_error('EVAL'); |
|
|
651 | } |
|
|
652 | return $vec_ref; |
|
|
653 | }else{ |
|
|
654 | return 0; |
|
|
655 | } |
|
|
656 | |
|
|
657 | } |
|
|
658 | } |
|
|
659 | |
|
|
660 | if( ref( $vec_ref ) eq 'AnswerHash' ){ |
|
|
661 | $vec_ref->{score} = 1; |
|
|
662 | $vec_ref; |
|
|
663 | }else{ |
|
|
664 | 1; |
|
|
665 | } |
|
|
666 | } |
|
|
667 | |
|
|
668 | sub display_correct_vecs{ |
|
|
669 | my ( $vec_ref,%opts ) = @_; |
|
|
670 | my $corr_matrix; |
|
|
671 | my @vecs = (); |
|
|
672 | |
|
|
673 | if( ref($vec_ref) eq 'AnswerHash' ) |
|
|
674 | { |
|
|
675 | $corr_matrix = Matrix->new_from_col_vecs($vec_ref->{correct_ans}); |
|
|
676 | }else{ |
|
|
677 | $corr_matrix = Matrix->new_from_col_vecs($vec_ref); |
|
|
678 | } |
|
|
679 | |
|
|
680 | my @temp = (); |
|
|
681 | |
|
|
682 | for( my $i = 0 ; $i < $corr_matrix->[2] ; $i++ ){ |
|
|
683 | push @temp, display_matrix($corr_matrix->column($i)); |
|
|
684 | push @temp, ","; |
|
|
685 | } |
|
|
686 | |
|
|
687 | if( def(@temp) ) |
|
|
688 | { |
|
|
689 | pop @temp; |
|
|
690 | }else{ |
|
|
691 | @temp = [[" "]]; |
|
|
692 | } |
|
|
693 | |
|
|
694 | |
|
|
695 | |
|
|
696 | mbox(\@temp); |
|
|
697 | |
|
|
698 | } |
|
|
699 | |
| 633 | 1; |
700 | 1; |