Forums

Search results: 133

WeBWorK Problems -> compoundProblem.pl errors

by Balagopal Pillai -
Hi,

           One of the webwork problems is throwing the following error -
 
           ERRORS from evaluating PG file: 
Error detected while loading [PG]/macros/compoundProblem.pl: PG_macro_file_eval detected error at line 123 of file [PG]/lib/PGloadfiles.pm Can't use 'defined(%hash)' (Maybe you should just omit the defined()?) at line 585 of [PG]/macros/compoundProblem.pl, chunk 1. The calling package is PGloadfiles Died within PGloadfiles::compile_file called at line 171 of [PG]/lib/PGloadfiles.pm from within PGloadfiles::loadMacros called at line 514 of [PG]/macros/PG.pl from within main::loadMacros called at line 14 of (eval 1626) 

         The OS is ubuntu 16.04 and perl version is 5.22 and the pg file uses compoundProblem.pl. This used to work last term with debian 8 and perl 5.20. 
         I noticed the following -
 
         from debian 8 - 
 
 
defined(%hash) is deprecated at compoundProblem.pl line 583.
(Maybe you should just omit the defined()?)
from ubuntu 16.04 - 
Can't use 'defined(%hash)' (Maybe you should just omit the defined()?) at compoundProblem.pl line 583.
      Looks like a warning on the old perl version turned out to be an error on the new version. I was wondering if there is a work around for this or may be an updated version of compoundProblem.pl available. Thanks a lot.


Balagopal
Hi Joel,

The first pg problem below uses PGML and scaffold.pl
  • http://webwork.maa.org/wiki/Scaffolding2
  • https://github.com/openwebwork/pg/blob/master/macros/scaffold.pl
and harvests the student's first answer using

$inputs_ref->{ANS_NUM_TO_NAME(1)}

The second pg problem below uses only BEGIN_TEXT / END_TEXT and recycles some code from the CompoundProblems that came before scaffold.pl
  • http://webwork.maa.org/wiki/CompoundProblems
and harvests the student's score and answer from the answer hash via

$ans_hash1 = $answer1->cmp()->evaluate( $inputs_ref->{ANS_NUM_TO_NAME(1)} );
$answer1_score = $ans_hash1->{score};
$answer1_student = $ans_hash1->{original_student_ans};

You can also use the listEnvironmentVariables() subroutine in PGinfo.pl to view the environment variables, such as what's stored in $inputs_ref. 

Best regards,

Paul Pearson

#####################################

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGML.pl",
"scaffold.pl",
"PGcourse.pl",
"PGgraphmacros.pl",
"PGinfo.pl",
);

TEXT(beginproblem());

Context("Numeric");

$answer1 = Compute("sin(x)");

Scaffold::Begin(
  can_open => "when_previous_correct",
  is_open  => "first_incorrect"
);
 
Section::Begin("Part 1: The first part");
BEGIN_PGML
Enter [` \sin(x) `] [________]{$answer1}
END_PGML
Section::End();

$answer1_student = $inputs_ref->{ANS_NUM_TO_NAME(1)}; # alternate, perhaps more direct method

$gr = init_graph(-4,-1,4,1,
axes=>[0,0],
grid=>[8,2],
size=>[400,400]
);

add_functions($gr, "$answer1_student for x in <-4,4> using color:blue and weight:2");

Section::Begin("Part 2: The second part");
BEGIN_PGML
The student's first answer was [$answer1_student].  Here's a graph of the student's answer:

[@ image( insertGraph($gr), width=>200,height=>200,tex_size=>800 ) @]*
END_PGML
Section::End();

Scaffold::End();

ENDDOCUMENT();

###########################################

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGML.pl",
"scaffold.pl",
"PGcourse.pl",
"PGgraphmacros.pl",
"PGinfo.pl",
);

TEXT(beginproblem());

Context("Numeric");

$answer1 = Compute("sin(x)");


BEGIN_TEXT
Enter \( \sin(x) \) \{ $answer1->ans_rule(10) \}
END_TEXT

ANS( $answer1->cmp );

$ans_hash1 = $answer1->cmp()->evaluate( $inputs_ref->{ANS_NUM_TO_NAME(1)} );
$answer1_score = $ans_hash1->{score};
$answer1_student = $ans_hash1->{original_student_ans};

# $answer1_student = $inputs_ref->{ANS_NUM_TO_NAME(1)}; # alternate, perhaps more direct method


$gr = init_graph(-4,-1,4,1,
axes=>[0,0],
grid=>[8,2],
size=>[400,400]
);

add_functions($gr, "$answer1_student for x in <-4,4> using color:blue and weight:2");


if ( $ans_hash1->{score} == 1 ) {
BEGIN_TEXT
The student's first answer was $answer1_student.  Here's a graph of the student's answer:

\{ image( insertGraph($gr), width=>200,height=>200,tex_size=>800 ) \}
END_TEXT
}

BEGIN_TEXT
$PAR
\{ 
listEnvironmentVariables() 
\}
END_TEXT
ENDDOCUMENT();
I think I have this problem solved now!

It came down to using a combination of bizarroArithmetic and a list_checker.  Before I had been checking each element of the set one at a time and it was causing trouble by claiming that even non-fractions were unsimplified when the answer was not working (see my first question in this thread).

Here is the checker I used for the solution set:

\{SECTION_ANS($solset->cmp(entry_type => "a solution",
 list_checker => sub {
     my ($correct,$student,$ansHash,$value) = @_;
     my $n = scalar(@$student);  # number of student answers
     my $score = 0;              # number of correct student answers
 
     return 0 if $ansHash->{isPreview};
     $student = $ansHash->{student_formula};
     $correct = $ansHash->{correct_ans};
     $student = Formula("$student"); $correct = Formula("$correct");
     return 0 unless ($correct == $student);
     Context()->flags->set(bizarroDiv=>1);
     delete $correct->{test_values}, $student->{test_values};
     my $OK = (($correct == $student) or ($student == $correct)) ;
     Context()->flags->set(bizarroDiv=>0);
     Value::Error("Your answer is correct, but please simplify it further.") unless $OK;
     if ($OK) {$score = $n};
     return $score;
}
))

To remind you, here is how I had defined the solutions $an1 and $an2 and $solset:

Context("LimitedFraction")->flags->set(reduceFractions => 0);

$an1 = Fraction(1,$a);
$an2 = Fraction($a,1);


Context("Inequalities-AllowStrings");
Context()->variables->are(n=>'Real');
Context()->strings->add("No solution"=>{NONE});
Parser::Number::NoDecimals;
Context()->operators->set(
'/' => {class => 'bizarro::BOP::divide', isCommand => 1},
'//' => {class => 'bizarro::BOP::divide', isCommand => 1},
' /' => {class => 'bizarro::BOP::divide', isCommand => 1},
'/ ' => {class => 'bizarro::BOP::divide', isCommand => 1},
);
Context()->flags->set(
  reduceConstants=>0, # no decimals
  reduceConstantFunctions=>0, # combine 4+5*2?
  formatStudentAnswer=>'parsed', # no decimals
);

$solset = Compute("{$an1, $an2}");



I was able to find a way to get the compound assignment statement to work properly using code from the PCC problems (see below), but I still am not able to get it to work for the solution sets {2/6, 3}.  Basically, it appears that I just don't know the parameters well enough to adjust this code to work with it correctly.  Anyone able to help with this part?

Thanks!

Paul

Context("LimitedFraction")->flags->set(reduceFractions => 0);
Context()->variables->are(n=>'Real');
Context()->strings->add("No solution"=>{NONE});
parser::Assignment->Allow;
Context()->operators->redefine(',',using=>',',from=>'Numeric');
Context()->operators->redefine('or',using=>',',from=>'Numeric');
Context()->operators->set(
  ','=>{string=>' or ',TeX=>'\hbox{ or }'},
  'or'=>{string=>' or ',TeX=>'\hbox{ or }'}
);
Context()->lists->set(List => {separator => " or "});

$an1 = Fraction(1,$a)->reduce;
$an2 = Fraction($a,1);
$possols = Compute("n = $an1 or n = $an2");

and later:

ANS($possols->cmp(  entry_type => "a solution",
  checker => sub {
    my ($correct,$student,$ans,$nth,$value) = @_;
    if ($correct->type eq "Assignment") {
      my ($svar,$sfrac) = $student->value; # get the variable and fraction
      #return 0 unless Value::classMatch($sfrac,'Fraction') && $sfrac->isReduced;
      if(Value::classMatch($sfrac,'Fraction'))
      {
        return 0 unless $sfrac->isReduced;
      }
    }
    return $correct == $student;
  },
  extra => sub {
    my ($student,$ansHash,$nth,$value) = @_;
    if($student eq "No solution")
    {
         $student->context->setError("This equation does have some solutions- look back at your work","",undef,undef,$Value::CMP_WARNING)
         unless $ans->{isPreview};
         return;
    }
    if ($student->type ne "Assignment" && $ansHash->{student_formula}->type ne "Assignment") {
      $student->context->setError("Your $nth solution should be written n = $US$US$US","",undef,undef,$Value::CMP_WARNING)
         unless $ans->{isPreview};
      return;
    }
    my ($svar,$sfrac) = $student->value; # get the variable and fraction
    if (Value::classMatch($sfrac,'Fraction') && !$sfrac->isReduced) {
      $student->context->setError("Your $nth $value is not reduced","",undef,undef,$Value::CMP_WARNING)
         unless $ans->{isPreview};
      return;
    }
    return Value::Real->typeMatch($student);
  }
))
Hello!

I am having trouble getting the following feedback when using bizarroArithmetic to check for unreduced fractions in solution sets, like {2/6, 3} or compound statements, like: n = 2/6 or n = 3. For some reason it is telling the student that both numbers need to be simplified, when only one of them is unreduced.

Here's the feedback for the above answers. It's the same for both versions.

There is a problem with your first number:
Your answer is correct, but please simplify it further
There is a problem with your second number:
Your answer is correct, but please simplify it further

Is there a way I can adjust the checker to respond correctly?

Thanks!

Here is the code:

## DESCRIPTION
## Algebra: Fractional equations
## ENDDESCRIPTION

## Paul added multiple steps to this problem.
## DBsubject(Algebra)
## DBchapter(Rational equations and functions)
## DBsection(Rational equations)
## Date(11/14/2014) ## Created 10/26/2009
## Institution(University of Minnesota, Monroe Community College)
## Author(Jonathan Rogness, Paul Seeburger)
## Level(2)
## TitleText1('Algebra for College Students')
## AuthorText1('Kaufmann, Schwitters')
## EditionText1('8')
## Section1('4.6')
## Problem1('15')
## KEYWORDS('algebra', 'fractional equations')
## adapted from: Library/UMN/algebraKaufmannSchwitters/ks_4_6_15.pg

########################################################################

DOCUMENT();

loadMacros(
"PGstandard.pl", # Standard macros for PG language
"MathObjects.pl",
"compoundProblem5.pl",
"contextInequalitiesAllowStrings.pl",
"contextFraction.pl",
"bizarroArithmetic.pl",
"contextLimitedFactor.pl",
#"source.pl", # allows code to be displayed on certain sites.
"PGcourse.pl" # Customization file for the course
);

########################################################################
$scaffold = Scaffold();
#$isInstructor = ($envir{effectivePermissionLevel} >= $envir{ALWAYS_SHOW_SOLUTION_PERMISSION_LEVEL});
$isInstructor=0; # This variable changes what the user can see.
INITIALIZE_SCAFFOLD('$scaffold');

TEXT(beginproblem());

$showPartialCorrectAnswers = 1;

########################################################################

Context("Numeric");
Context()->variables->are(n=>'Real');
Context()->strings->add(none=>{},EmptySet=>{alias=>"none"});

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

$b = Compute("$a*$a+1");

$lhs = Compute("n+1/n");

$LCD = Compute("$a n");

$lhs2 = Compute("$a n^2 + $a");
$rhs2 = Compute("$b n");

$extr = Compute("None");

$an2 = Compute("$a");

Context("Fraction");
Parser::Number::NoDecimals;
Context()->operators->set(
'/' => {class => 'bizarro::BOP::divide', isCommand => 1},
'//' => {class => 'bizarro::BOP::divide', isCommand => 1},
' /' => {class => 'bizarro::BOP::divide', isCommand => 1},
'/ ' => {class => 'bizarro::BOP::divide', isCommand => 1},
);
Context()->flags->set(
reduceConstants=>0, # no decimals
reduceConstantFunctions=>1, # combine 4+5*2?
formatStudentAnswer=>'parsed', # no decimals
);

$an1 = Fraction(1,$a)->reduce;


Context("Inequalities-AllowStrings");
Context()->variables->are(n=>'Real');
Context()->strings->add("No solution"=>{NONE});
Parser::Number::NoDecimals;
Context()->operators->set(
'/' => {class => 'bizarro::BOP::divide', isCommand => 1},
'//' => {class => 'bizarro::BOP::divide', isCommand => 1},
' /' => {class => 'bizarro::BOP::divide', isCommand => 1},
'/ ' => {class => 'bizarro::BOP::divide', isCommand => 1},
);
Context()->flags->set(
reduceConstants=>0, # no decimals
reduceConstantFunctions=>1, # combine 4+5*2?
formatStudentAnswer=>'parsed', # no decimals
);

$possols = Compute("n = $an1 or n = $an2");
# $possols = Compute("n = 1/$a or n = $an2");

$solset = Compute("{1/$a, $a}");

Context("LimitedFactor");
Context()->variables->are(n=>'Real');
Context()->noreduce('(-x)-y','(-x)+y');
$factored = Formula("($a n - 1)*(n - $a)");

########################################################################

Context()->texStrings;
BEGIN_TEXT
Solve the equation: $SPACE $SPACE$SPACE
\( \large \displaystyle {$lhs = \frac{$b}{$a}}
\)

$PAR
$PAR
END_TEXT

DISPLAY_SECTION( { name=>"1. Determine the LCD of the fractions in the equation",
canshow =>1, #always true
iscorrect=>$scaffold->requireCorrect(1),
section=>1 #designates that this is the first section
} , <<'END_SECTION');

$PAR
LCD = \{SECTION_ANS($LCD->cmp), $LCD->ans_rule(10)\}

END_SECTION
Context()->normalStrings;

############
## Section 2
############

Context()->texStrings;
DISPLAY_SECTION( { name=>"2. Clear the fractions",
canshow =>$scaffold->requireCorrect(1). " or $isInstructor",
iscorrect=>$scaffold->requireCorrect(2,3),
section=>2
}, <<'END_SECTION');
$PAR
Multiply both sides of the equation by this LCD and simplify each side to cancel the denominators.
$BR $BR \( \displaystyle {$a n \cdot \left( $lhs \right) = $a n \cdot \frac{$b}{$a}}\)
$BR $BR Enter the resulting expressions you obtain on each side of the equation.
$BR $BR \{ans_rule(10)\} = \{ans_rule(10)\}

END_SECTION
Context()->normalStrings;

SECTION_ANS($lhs2->cmp, $rhs2->cmp);

##############
# Section 3
##############

Context()->texStrings;
DISPLAY_SECTION(
{ name=>"3. Rewrite the equation, solve by factoring, and check answers",
canshow =>$scaffold->requireCorrect(2,3). " or $isInstructor",
iscorrect=>$scaffold->requireCorrect(6),
section=>3
}, <<'END_SECTION');

Rewrite this equation so that it is equal to zero, and the left side has a positive leading coefficient. Then factor the left side. $PAR
\{ANS($factored->cmp), $factored->ans_rule(15) \} \( = 0 \)
$PAR
Solving this equation gives what possible solutions? Enter your answers in the form: \(n = \) ______ or \(n = \) ______
$PAR
\{ SECTION_ANS($possols->cmp(
checker=>sub{
my ( $correct, $student, $ansHash ) = @_;
return 0 if $ansHash->{isPreview};
$student = $ansHash->{student_formula};
$correct = $ansHash->{correct_ans};
$student = Formula("$student"); $correct = Formula("$correct");
return 0 unless ($correct == $student);
Context()->flags->set(bizarroDiv=>1);
delete $correct->{test_values}, $student->{test_values};
my $OK = (($correct == $student) or ($student == $correct));
Context()->flags->set(bizarroDiv=>0);
Value::Error("Your answer is correct, but please simplify it further") unless $OK;
return $OK;
})), $possols->ans_rule(30) \}
$PAR
Which of these possible solutions are extraneous (because they make the equation undefined)? $BR
If none are, enter $BBOLD None$EBOLD. \{ SECTION_ANS($extr->cmp), $extr->ans_rule(10) \}
$PAR
Finally, the solution set is:
\{SECTION_ANS($solset->cmp(
checker=>sub{
my ( $correct, $student, $ansHash ) = @_;
return 0 if $ansHash->{isPreview};
$student = $ansHash->{student_formula};
$correct = $ansHash->{correct_ans};
$student = Formula("$student"); $correct = Formula("$correct");
return 0 unless ($correct == $student);
Context()->flags->set(bizarroDiv=>1);
delete $correct->{test_values}, $student->{test_values};
my $OK = (($correct == $student) or ($student == $correct)) ;
Context()->flags->set(bizarroDiv=>0);
Value::Error("Your answer is correct, but please simplify it further") unless $OK;
return $OK;
},showHints=>0)), $solset->ans_rule(15) \}
END_SECTION
Context()->normalStrings;



# \{ans_rule(15) \} \( = 0 \)
# \{SECTION_ANS($factored->cmp), $factored->ans_rule(15) \} \( = 0 \)
# ANS($factored->cmp());

#SECTION_ANS($factored->cmp(), $extr->cmp());

##############
# Section 4
##############

#Context()->texStrings;
#DISPLAY_SECTION(
#{ name=>"4. Solve the equation for the possible solutions",
# canshow =>$scaffold->requireCorrect(4,5). " or $isInstructor",
# iscorrect=>$scaffold->requireCorrect(6),
# section=>4
#}, <<'END_SECTION');

#Finally, the solution set is:
#\{SECTION_ANS($solset->cmp), $solset->ans_rule(15) \}
#END_SECTION
#Context()->normalStrings;


####################################
PROCESS_ANSWERS();

$last_correct_section = PROCESS_SECTIONS();

$opensection = $last_correct_section + 1;
for ($i = 1; $i<= $opensection; $i++) {
$scaffold->openSections($i);
}

TEXT($END_ONE_COLUMN);
ENDDOCUMENT();

WeBWorK Problems -> New compoundPorblem5.pl Question

by Paul Seeburger -
I am trying to use the newer version of compoundProblem5.pl in the develop branch found here.

Perhaps this macro needs to be placed somewhere other than in my user macro folder as I cannot even get the sample coded problem to work using it.

Here is the error I am seeing:

ERROR caught by Translator while processing problem file:local/setHW24-RationalEquations/blankProblem2.pg
****************
ERRORS from evaluating PG file: 
Can't find string terminator " END_SECTION" anywhere before EOF at line 44 of (eval 16608)



$scaffold = Scaffold();   # create the scaffold
Context("Numeric");
##########################################
#  Section 1
##########################################
$f = Compute("x^2-1");
Context()->texStrings;
DISPLAY_SECTION("Section 1: The equation",<<'END_SECTION');
 Enter the function \($f\): \{ SECTION_ANS($f->cmp); $f->ans_rule(10) \}
END_SECTION
Context()->normalStrings;
##########################################
#  Section 2
##########################################
$x = Compute("sqrt(3)/2");
DISPLAY_SECTION("Section 2: The number",<<'END_SECTION');
 What is \(\sin(\pi/3)\)? \{ SECTION_ANS($x->cmp); $x->ans_rule \}
END_SECTION
##########################################
PROCESS_SCAFFOLD();
ENDDOCUMENT(); 

Oddly, I am getting a different error on another larger problem that I am creating.  It seems to be having trouble even loading the macro compoundProblem5.pl.

My loading code:

loadMacros(
   "compoundProblem5.pl",
   "PGstandard.pl",     # Standard macros for PG language
   "MathObjects.pl",
   "contextInequalitiesAllowStrings.pl",
   "contextLimitedFactor.pl",
   #"source.pl",        # allows code to be displayed on certain sites.
   "PGcourse.pl"     # Customization file for the course
);

The error:

WeBWorK Problems -> Scaffolded problems

by Paul Seeburger -
So I am still a little unsure about which version of scaffolded problems I should be trying right now, but for now I have been experimenting with CompoundProblem5.pl, the version that is already in the standard WeBWorK 2.8 and pg_version 2.8.1.

I am trying to figure out how to make all parts that have already been answered correctly remain open (not folded away).  It appears that the only way to do this is to create a statement for each step I want visible, or to use a loop as follows:

$opensection = $last_correct_section + 1;
for ($i = 1; $i<= $opensection; $i++) {
   $scaffold->openSections($i);
}

It seems that there should be a cleaner way to specify this, as I would expect it to be a common request.  Perhaps, openSections("all") could work.

Related to this question, I was reading about some of the newer versions of this scaffolding process and it appeared that the examples I saw left out the line to specify which step(s) to open altogether.  I am hoping there may still be an easier (cleaner) way to make multiple parts visible and that the newer techniques don't assume we would only want the current not-yet-correctly answered section made visible.

Also, I am curious about using a weighted grader in this context.  Is it possible?  I saw a post implying that it is not at this point.

Thanks!

Paul
Thanks to you all for the progress that's been made. In the old days, I could use compoundProblem with the weightedAnswer grader. I have a number of problems where I want to give far more weight to the latter parts of the problem, as opposed to the earlier parts, for example.

Is there any hope for this to wend its way back into working? :)

In the meantime I'm living with compoundProblem5.pl and the students are having all the parts weighted equally.


There is also a newer version of compoundProblem5.pl in the development branch, and you can view it or use the "raw" button to get a copy. It simplifies things considerably and adds PGML support, but it is still not quite so easy as the newer scaffold.pl that Mike mentioned.

There is now some documentation at the top of the compoundProblem5.pl file, with a sample shell of a problem. There is a complete example in the pull request. The older code requires you to keep track of all the answers in all the parts, but the new version doesn't, so the Wiki example Mike linked to is more complicated than it has to be now. There is also a new PROCESS_SCAFFOLD() call that takes care of all the details in the bottom section of the Wiki example.

I just noticed that the documentation at the top of the file calls it scaffold.pl rather than compoundProblem5.pl. I will have to change that, but it was that way because I was going to change the name before I wrote the new scaffold.pl from scratch.
This is a good method for the approach you are using.

If you would like a better idea of what data is available to you in any problem, temporarily put "PGinfo.pl" in your loadMacros list  and then use

listVariables();  anywhere in the perl code sections of the problems.  (It doesn't go inside TEXT() function -- it prints itself.)

This will print out a complete list of all of the variables that you can access when writing a PG problem.  You won't need most of them of course.

For your original question about writing a sequential problem which hides the second part until the student gets the first part right  there have been a number of approaches starting with the macro file compoundProblem.pl, through compoundProblem5, and the best of the macro packages is called scaffold.pl (completed by Davide Cervone this summer).  


I think it will do what you want.  scaffold.pl is not yet in either the master or the develop version of pg yet.  It is pull request #153 
https://github.com/openwebwork/pg/pull/153 
so you can download it and install it yourself if you wish.

The best version for scaffolded problems that currently exists in the standard "master" distribution of webwork is compoundProblem5 and is described here: 


(scaffold.pl is better -- so I recommend that if at all possible.)