WeBWorK Problems

Answer dependent on student response

Answer dependent on student response

by Gregory Varner -
Number of replies: 15

I am wondering if the following would be possible (it seems like it should be, but I am having trouble figuring out how to go about it).

I am working on regression where the students need to decide between several different options of what curve to use (for instance, linear, quadratic, exponential, logarithmic, and logistic curves).

I first want to accept potentially several of them as correct (I am thinking a custom checker that would return 1 if it is one of the possible answers but there is probably a better way). They will have to justify their answer elsewhere.

I would then want them to solve a question using the curve that they chose. So I would need something to the effect of

if($studentans1=linear, $ans2=......)

if($studentans1=quadratic, $ans2=....)

and so on.

Any suggestions on how I might go about this are appreciated. 

In reply to Gregory Varner

Re: Answer dependent on student response

by Glenn Rice -

This will definitely take a custom grader.  There are several ways to achieve this.  One is to use a MultiAnswer.  Then you have access to the answers for all parts in the grader.

You can also store the answer evaluator (return by the cmp method of the object) of those answers in a variable that you can pass the ANS (or use in PGML).  Then you can access the answer hash for those parts in later custom graders.  This is the more complicated method, but can be more powerful.

In reply to Glenn Rice

Re: Answer dependent on student response

by Danny Glin -
MultiAnswer is set up to do exactly this sort of thing.  As Glenn says you will have to write a custom answer checker to go with it.

The wiki page on MultAnswer Problems should be helpful:
https://webwork.maa.org/wiki/MultiAnswerProblems


In reply to Danny Glin

Re: Answer dependent on student response

by Gregory Varner -

I could use some more help if possible.

My current plan is to allow the students to pick between several different types of regression. However, I am also wanting to control the accuracy of their answers. I have a checker for the "linear" case but it is not returning values like I would expect. I only have the initial line for the "exponential" case because once I have the linear case it will be just modifying it.

I considered using the student's answers in the multianswer so that the answer checker would base answers off of their input instead of the "correct answer," but the number of variables and the numerical tolerance were a potential issue (maybe someday when I have lots of time...)

I also have things set up so that I can easily modify or even later randomize if I wanted to. (And only linear and quadratic are currently being calculated.)

Here is what I have:


DOCUMENT();        # This should be the first executable line in the problem.

loadMacros(

  "PGstandard.pl",

  "MathObjects.pl",

  "answerHints.pl",

  "PGchoicemacros.pl",

    "PGcourse.pl",

    "parserMultiAnswer.pl",

);

TEXT(beginproblem());

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

#  Set-up

$points = 5;

$x[0] = 10;

$x[1] = 20;

$x[2] = 30;

$x[3] = 40;

$x[4] = 45;


$y[0] = 16.0;

$y[1] = 20.3;

$y[2] = 21.9;

$y[3] = 23.3;

$y[4] = 23.9;


$year = 2020;

$mpg = 100;

#############linear regression

$sx =0;

$sy =0;

$sxy =0;

$sx2 =0;

$sy2 =0;

$sx3 =0;

$sx4 =0;

$sx2y =0;

$meanx =0;

$meany =0;

$sse =0;

$sst =0;

for($i=0; $i<$points; $i++) {

#####sum of x

$sx = $sx + $x[$i];

#####sum of y

$sy = $sy + $y[$i];

#####sum of xy

$sxy = $sxy + ($x[$i]*$y[$i]);

#####sum of x^2

$sx2 = $sx2 + ($x[$i]*$x[$i]);

#####sum of y^2

$sy2 = $sy2 + ($y[$i]*$y[$i]);

#####sum of x^3

$sx3 = $sx3 + ($x[$i]*$x[$i]*$x[$i]);

#####sum of x^4

$sx4 = $sx4 + ($x[$i]*$x[$i]*$x[$i]*$x[$i]);

#####sum of x^2 y

$sx2y = $sx2y + ($x[$i]*$x[$i]*$y[$i]);

#####for the mean

$meanx = $meanx+$x[$i];

#####for the mean

$meany = $meany+$y[$i];

}

######mean of x

$meanx = $meanx/$points;

######mean of y

$meany = $meany/$points;


######linear regression terms

$ssxy = $points*$sxy-(($sx*$sy));

$ssx = $points*$sx2-($sx*$sx);

$ssy = $points*$sy2-($sy*$sy);


########linear regression calculation

$r = sprintf("%0.5f",$ssxy/sqrt($ssx*$ssy));

$r2 = sprintf("%0.3f",$r*$r);


$b1 = sprintf("%0.3f",$ssxy/$ssx);

$b0 = sprintf("%0.3f",$meany-$b1*$meanx);


######quadratic regression terms

$qa = (($points*$sx2y- $sx2*$sy)*($points*$sx2 -$sx*$sx)-

      ($points*$sxy-$sx*$sy)*($points*$sx3 -$sx*$sx2))/

      (($points*$sx2 -$sx*$sx)*($points*$sx4 -($sx2*$sx2))-

      ($points*$sx3-$sx*$sx2)*($points*$sx3-$sx*$sx2));

$a = sprintf("%0.4f",$qa);

$qb = (-($points*$sx2y- $sx2*$sy)*($points*$sx3-$sx*$sx2)+

      ($points*$sxy-$sx*$sy)*($points*$sx4 -($sx2*$sx2)))/

      (($points*$sx2 -$sx*$sx)*($points*$sx4 -($sx2*$sx2))-

      ($points*$sx3-$sx*$sx2)*($points*$sx3-$sx*$sx2));

$b = sprintf("%0.4f",$qb);       

$qc = ($sy/$points)-$qb*($sx/$points)-$qa*($sx2/$points);

$c = sprintf("%0.4f",$qc);    


######for quadratic r^2

for($i=0; $i<$points; $i++) {

######for SST

    $sst = $sst + ($y[$i]-$meany)*($y[$i]-$meany);

#####for SSE

    $sse = $sse + ($y[$i]-$qa*$x[$i]*$x[$i] -$qb*$x[$i] -$qc)*($y[$i]-$qa*$x[$i]*$x[$i] -$qb*$x[$i] -$qc);

}

$qr = sprintf("%0.3f",1-($sse/$sst));

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

####multianswer

 Context("Vector");

Context()->strings->add("no solution"=>{},

  "no solutions"=>{alias=>'no solution'}, 

  "none"=>{alias=>'no solution'});

Context()->strings->add("linear"=>{});

Context()->strings->add("exponential"=>{});

Context()->strings->add("logarithmic"=>{});

Context()->strings->add("logistic"=>{});

Context()->strings->add("quadratic"=>{});


$ans_5 = String("logarithmic");

$ans_6 = $b0 + $b1*($year-1970);

$ans_7 = ($mpg-$b0)/($b1);


$multians = MultiAnswer($ans_5, $ans_6, $ans_7)->with(

  singleResult => 0,

  checker => sub {

      my ( $correct, $student, $self ) = @_;

      my ( $a1s, $a2s, $a3s ) = @{$student};

      my ( $a1, $a2, $a3 ) = @{$correct};

      if ( $a1s == "linear"){ 

            if ($a2s == $b0+$b1*($year-1970) && $a3s == $a3) {$self->setMessage(1,"A line is not the best choice.");

  return [0,1,1]}

            elsif ($a2s == $b0+$b1*($year-1970) && $a3s != ($mpg-$b0)/$b1) {$self->setMessage(1,"A line is not the best choice.");

  return [0,1,0]}

            elsif ($a2s != $b0+$b1*($year-1970) && $a3s == ($mpg-$b0)/$b1) {$self->setMessage(1,"A line is not the best choice.");

  return [0,0,1]}

            else {return [0,0,0]};}

      elsif ($a1s == "exponential" && $a2s == 25.4 && $a3s == 187.9) {$self->setMessage(1,"A exponential is not the best choice.");

  return [0,1,1]}

       else {

              return [0,0,0];

          }

      }

);

  

#  Main


BEGIN_TEXT


$PAR

$BBOLD Note on Rounding: Your answers are dependent on rounding. Be sure to round as the problem specifies. $EBOLD

$PAR

$BR

The following questions use the following information from the U.S. Department

of Transportation.


$BR

\{begintable(2)\}

\{row("Years after 1970", "Avg. Number of MPG for U.S. Automobiles (light duty)")\}

\{row("\($x[0]\)", "\($y[0]\)")\}

\{row("\($x[1]\)", "\($y[1]\)")\}

\{row("\($x[2]\)", "\($y[2]\)")\}

\{row("\($x[3]\)", "\($y[3]\)")\}

\{row("\($x[4]\)", "\($y[4]\)")\}

\{endtable()\}

 $BR


(a) Find the linear , quadratic, exponential, logistic, and logarithmic regression models that gives the miles per gallon

as a function of years after 1970. (Round answers to three decimal places.)

$PAR

\(y = \) \{ans_rule(2)\} \(x + \) \{ans_rule(2) \} 

 with \(r^2 = \) \{ans_rule(15)\}. 

 

$PAR

$BR


\(y = \) \{ans_rule(15)\}

 with \(r^2 = \) \{ans_rule(15)\}. 

 

$PAR

$BR

$BR


b) Which of the better model to use? (Please enter "linear, quadratic, exponential, logistic or logarithmic.")


$Par

$BR


The best model to use is \{$multians->ans_rule(15)\}


$PAR

$BR

$BR


c) For the model chosen in the last part, what is the average miles per gallon expected to be in $year? (Round to 1 decimal place.)


$BR


The average miles per gallon in $year is predicted to be \{$multians->ans_rule(15)\} mpg.


$PAR

$BR

$BR


d) For the model chosen, when will the miles per gallon be $mpg? (Depending on your, choice you may

have no solution or very large numbers. Round any decimals to one place.)


$BR 


We predict that the mpg will be $mpg \{$multians->ans_rule(15)\} years after 1970.


END_TEXT

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

#  Answers


$showPartialCorrectAnswers = 1;


$ans_1m = $b1;

$ans_1 = $b0;

ANS(num_cmp($ans_1m,tolType => 'absolute',

  tolerance => .002));

 

ANS(num_cmp($ans_1,tolType => 'absolute',

  tolerance => .002));

$ans_2 = Compute($r2)->with(tolType=>'absolute', tolerance=>'0.002');


  ANS($ans_2->cmp->withPostFilter(AnswerHints(

          sub {


                my ($correct,$student,$anshash) = @_;


                return abs($student-$correct) < .01;


                } => ["Your answer is close.  Try the calculation using more accuracy."])));

                

            

$ans_3 = "$c + $b*x +$a*x^2";

ANS(fun_cmp($ans_3,tolType => 'absolute',

  tolerance => .0001));


$ans_4 = Compute($qr)->with(tolType=>'absolute', tolerance=>'0.002');


  ANS($ans_4->cmp->withPostFilter(AnswerHints(


           sub {


                my ($correct,$student,$anshash) = @_;


                return abs($student-$correct) < .01;


                } => ["Your answer is close.  Try the calculation using more accuracy."])));

  

ANS($multians->cmp(tolType => 'absolute',

  tolerance => .1)); 


ENDDOCUMENT();       # This should be the last executable line in the problem.

In reply to Gregory Varner

Re: Answer dependent on student response

by Danny Glin -

It looks like three different things are getting in the way of the tolerance being respected within the MultiAnswer object:

  1. You are comparing the student's answer to a perl floating point number, and not a MathObject, so for example the quantity "$b0+$b1*($year-1970)" can not inherit the tolerance settings from the context.  The fix for this is to define such a quantity as a MathObject, i.e.
    $ans_6 = Compute($b0+$b1*($year-1970);
    Then use $ans_6 in the comparisons within your answer checker.
  2. You are setting the tolerance within the $multians->cmp() routine.  This should set the tolerance for the $multians object, but that won't be inherited by other quantities that are used in the custom answer checker.  This might be considered a bug in the MultiAnswer code.  In your code, $multians is made up of $ans_5, $ans_6, and $ans_7, but setting the tolerance for $multians doesn't appear to set the tolerance for those variables.  The fix for this is to set the tolerance for the individual quantities that you are comparing, i.e.
    $ans_6->{tolerance} = 0.1;
    $ans_6->{tolType}="absolute";
  3. I'm not sure if this one is even documented anywhere: when doing "fuzzy" comparisons with MathObjects (i.e. up to tolerance), the tolerance that is respected is that of the left hand side of the comparison.  This means that if you do the above, then the comparison
    $ans_6 == $a2s
    will return true if the values are within 0.1, but the comparison
    $a2s == $ans_6
    will use the tolerance settings for the context in which $a2s was created, which is probably the default relative tolerance.

In summary, here's what I did to your code to get the multianswer to accept an answer to part c within 0.1:

$ans_6 = Compute($b0 + $b1*($year-1970));

$ans_6->{tolerance}=0.1;

$ans_6->{tolType}="absolute";

...

if ($ans_6 == $a2s && ...

You will have to make the analogous changes for $ans_7 to adjust it's tolerance.


Some other observations:

Why are you introducing the vector context?  It doesn't look like you're using any vectors, and this leads to the possibility of misleading error messages to students?

I highly recommend when asking students to choose an answer from a fixed list that you use one fixed response constructions available in WeBWorK.  I like a pop up list for this question.  I know that they work with multianswer objects.  You could probably also use parserRadioButtons, but I haven't tried within a multianswer.

If you're doing a lot of statistical calculations, you should look at the R integration with WeBWorK.  I assume that R has built-in functions for all of these types of regression.

Instead of manually setting the number of points, you can use the scalar function to determine the size of an array.  i.e. after you have defined the array @x, you can use

$points = scalar(@x);

In reply to Danny Glin

Re: Answer dependent on student response

by Gregory Varner -
Thank you for catching the use of Vector context there when I didn''t need it. Fortunately it was not doing any harm at the moment, but I had accidentally copied to much over when I did that.

Thank you for the observations and your fix. The problem I am having is that I set initial values, but I want the student to be able to choose any of the types of regression and have their answer compared to the one that they would get from their choice.

For instance, if they chose exponential they are going to get different values for $ans_6 and $ans_7 than the formulas that the multianswer pulls in.

Basically I want them to be able to choose any of the string choices (linear, quadratic, logarithmic, etc.) and then compare the answers they give to the ones that they should get. Obviously a 10% threshold is quite large there. A 1-5 percent might be acceptable to me as that leaves room for rounding issues (this is regression after all). Is there a way to manually set the threshold for the entire problem so that multianswer will inherit it, but I can manually override it on other problems (such as when they give their regression equations)?

I will certainly have to look at the R integration with Webwork.
In reply to Danny Glin

Re: Answer dependent on student response

by Gregory Varner -

I do have a follow up question.

Is there any particular trick to using a pop-up menu in multi-answer.

I've used them before and have set the package to be used and defined

$pop = PopUp(["select","linear","quadratic","exponential","logistic","logarithmic"], "logarithmic");

I then included the pop-up menu in the problem and changed multianswer to call the pop-up.

However, I just get a message saying that the string is not defined. (strangely the pop-up menu is also appearing twice in my question even though I only include it once in the problem.)

I previously had it set up with the strings, which worked as long as they had a feedback message for each answer (so linear and exponential worked as they should using the custom checker included but any other said that it could not convert the word to a number unless I included a message for the first answer also).

I currently have it set-up to compare to floating point numbers because it needed to check against different numbers for each choice. It is also using the inherent 10% tolerance, but I am able to control that through Edfinity where the questions are asigned through to any percent or fixed tolerance I want.


Context()->strings->add("no solution"=>{},

  "no solutions"=>{alias=>'no solution'}, 

  "none"=>{alias=>'no solution'});

$pop = PopUp(["select","linear","quadratic","exponential","logistic","logarithmic"], "logarithmic");

$ans_6 = $b0 + $b1*($year-1970);

$ans_7 = ($mpg-$b0)/($b1);


$multians = MultiAnswer($pop, $ans_6, $ans_7)->with(

  singleResult => 0, allowBlankAnswers => 1,

  checker => sub {

      my ( $correct, $student, $self ) = @_;

      my ( $a1s, $a2s, $a3s ) = @{$student};

      my ( $a1, $a2, $a3 ) = @{$correct};

      if ( $a1s == "linear"){ 

            if ($a2s == $b0+$b1*($year-1970) && $a3s == ($mpg-$b0)/$b1) {$self->setMessage(1,"A line is not the best choice.");

  return [1,1,1]}

            elsif ($a2s == $b0+$b1*($year-1970) && $a3s != ($mpg-$b0)/$b1) {$self->setMessage(1,"A line is not the best choice.");

            $self->setMessage(3,"Check your calculation.");

  return [1,1,0]}

            elsif ($a2s != $b0+$b1*($year-1970) && $a3s == ($mpg-$b0)/$b1) {$self->setMessage(1,"A line is not the best choice.");

            $self->setMessage(2,"Check your calculation.");

  return [1,0,1]}

            else {$self->setMessage(1,"A line is not the best choice.");

            $self->setMessage(2,"Check your calculation.");

            $self->setMessage(3,"Check your calculation.");

            return [1,0,0]}}

      elsif ( $a1s == "quadratic"){ 

            if ($a2s == $a*($year-1970)**2 +$b*($year-1970) +$c && $a3s == "no solution") {

  return [1,1,1]}

            elsif ($a2s == $a*($year-1970)**2 +$b*($year-1970) +$c && $a3s != "no solution") {$self->setMessage(3,"Check your calculation.");

  return [1,1,0]}

            elsif ($a2s != $a*($year-1970)**2 +$b*($year-1970) +$c && $a3s == "no solution") {$self->setMessage(2,"Check your calculation.");

  return [1,0,1]}

            else {$self->setMessage(2,"Check your calculation.");

            $self->setMessage(3,"Check your calculation.");

            return [1,0,0]}}

        elsif ( $a1s == "exponential"){ 

            if ($a2s == 15.3285*(1.0107**($year-1970)) && $a3s == ln($mpg/15.3285)/ln(1.0107)) {$self->setMessage(1,"A exponential is not a good choice.");


  return [0,1,1]}

            elsif ($a2s == 15.3285*(1.0107**($year-1970)) && $a3s != ln($mpg/15.3285)/ln(1.0107)) {$self->setMessage(1,"A exponental is not a good choice.");

$self->setMessage(3,"Check your calculation.");

  return [0,1,0]}

            elsif ($a2s != 15.3285*(1.0107**($year-1970)) && $a3s == ln($mpg/15.3285)/ln(1.0107)) {$self->setMessage(1,"A exponential is not a good choice.");

$self->setMessage(2,"Check your calculation.");

  return [0,0,1]}

            else {$self->setMessage(1,"A exponential is not a good choice.");

            $self->setMessage(2,"Check your calculation.");

            $self->setMessage(3,"Check your calculation.");

            return [0,0,0]}}

        elsif ( $a1s == "logistic"){ 

            if ($a2s == 24.2704/(1+1.2059*exp(-0.08638*($year-1970))) && $a3s == "no solution") {

  return [1,1,1]}

            elsif ($a2s == 24.2704/(1+1.2059*exp(-0.08638*($year-1970))) && $a3s != "no solution") {$self->setMessage(3,"Check your calculation.");

  return [1,1,0]}

            elsif ($a2s != 24.2704/(1+1.2059*exp(-0.08638*($year-1970))) && $a3s == "no solution") {$self->setMessage(2,"Check your calculation.");

  return [1,0,1]}

            else {$self->setMessage(2,"Check your calculation.");

            $self->setMessage(3,"Check your calculation.");

            return [1,0,0]}}

        elsif ( $a1s == "logarithmic"){ 

            if ($a2s == 4.3528+5.1643*ln(($year-1970)) && $a3s == exp(($mpg-4.3528)/5.1643)) {

  return [1,1,1]}

            elsif ($a2s == 4.3528+5.1643*ln(($year-1970)) && $a3s != exp(($mpg-4.3528)/5.1643)) {$self->setMessage(3,"Check your calculation.");

  return [1,1,0]}

            elsif ($a2s != 4.3528+5.1643*ln(($year-1970)) && $a3s == exp(($mpg-4.3528)/5.1643)) {$self->setMessage(2,"Check your calculation.");

  return [1,0,1]}

            else {$self->setMessage(2,"Check your calculation.");

            $self->setMessage(3,"Check your calculation.");

            return [1,0,0]}}

       else {

              return [0,0,0];

          }

      }

);


b) Which of the better model to use? \{$pop->menu()\}


$PAR

$BR

$BR


c) For the model chosen in the last part, what is the average miles per gallon expected to be in $year? (Round to 1 decimal place.)


$BR


The average miles per gallon in $year is predicted to be \{$multians->ans_rule(15)\} mpg.


$PAR

$BR

$BR


d) For the model chosen, when will the miles per gallon be $mpg? (Depending on your, choice you may

have no solution or very large numbers. Round any decimals to one place.)


$BR 


We predict that the mpg will be $mpg \{$multians->ans_rule(15)\} years after 1970.


In reply to Gregory Varner

Re: Answer dependent on student response

by Danny Glin -

If you're using a popUp in a multiAnswer, you should be calling the popUp menu via the multiAnswer object and not directly.  i.e. you need to replace

\{$pop->menu()\}

with

\{$multians->menu()\}

That should make the student's answer available to the multiAnswer checker.

You can set the tolerance for the Context, which should be inherited by any objects subsequently created in that context.  See https://webwork.maa.org/wiki/NumericalTolerance.  You can then use the code I supplied to override this for a particular object.

In reply to Danny Glin

Re: Answer dependent on student response

by Gregory Varner -

Thank you for your help.

I had remembered that it was possible to set the tolerance for the entire class just before I saw your answer, so thank you for the link that shows how to do that.


I am still struggling with the pop-up menu in multianswer.

I had to replace \{$pop->menu()\} with \{$multians->ans_rule(10)\} for it to appear correctly. I am not sure why, but it kept not working with the menu in there. However, I am still receiving the String "linear" is not defined in this context. If I define it as String($pop) in the multianswer then the popup menu disappears. 

I figured out how to make everything do what I want without using the popup menu, but I really like the idea of the popup menu since it fixes student input errors.

Any ideas?


Thank you for your help!

In reply to Gregory Varner

Re: Answer dependent on student response

by Danny Glin -

Can you post your most recent version of the pg file as an attachment?

In reply to Gregory Varner

Re: Answer dependent on student response

by Davide Cervone -

Sorry I don't have time to check this carefully, but try using

$a1s->value == "logistic"

in your test instead. The $a1s variable holds a MathObject, so when you use ==, that means it will try to promote the string value to another MathObject by making a String object, which requires the string to be in the current context. I suspect that is where the error is coming from. but again, I haven't tested it.

In reply to Davide Cervone

Re: Answer dependent on student response

by Gregory Varner -

I apologize for the delay. It was a crazy week.


If I define the strings, I still get the mismatched answer blanks and the popup menu shows in the next answer blank. If I don't define the strings, then it says that logarithmic is not defined in this context.


DOCUMENT();        # This should be the first executable line in the problem.

loadMacros(

  "PGstandard.pl",

"MathObjects.pl",

  "answerHints.pl",

  "PGchoicemacros.pl",

    "PGcourse.pl",

    "parserMultiAnswer.pl",

    "parserPopUp.pl",

);


TEXT(beginproblem());

########only linear and quadratic are calculated in problem

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

#  Set-up

$points = 5;

$x[0] = 10;

$x[1] = 20;

$x[2] = 30;

$x[3] = 40;

$x[4] = 45;

$y[0] = 16.0;

$y[1] = 20.3;

$y[2] = 21.9;

$y[3] = 23.3;

$y[4] = 23.9;

$year = 2020;

$mpg = 100;

#############linear regression

$sx =0;

$sy =0;

$sxy =0;

$sx2 =0;

$sy2 =0;

$sx3 =0;

$sx4 =0;

$sx2y =0;

$meanx =0;

$meany =0;

$sse =0;

$sst =0;

for($i=0; $i<$points; $i++) {

#####sum of x

$sx = $sx + $x[$i];

#####sum of y

$sy = $sy + $y[$i];

#####sum of xy

$sxy = $sxy + ($x[$i]*$y[$i]);

#####sum of x^2

$sx2 = $sx2 + ($x[$i]*$x[$i]);

#####sum of y^2

$sy2 = $sy2 + ($y[$i]*$y[$i]);

#####sum of x^3

$sx3 = $sx3 + ($x[$i]*$x[$i]*$x[$i]);

#####sum of x^4

$sx4 = $sx4 + ($x[$i]*$x[$i]*$x[$i]*$x[$i]);

#####sum of x^2 y

$sx2y = $sx2y + ($x[$i]*$x[$i]*$y[$i]);

#####for the mean

$meanx = $meanx+$x[$i];

#####for the mean

$meany = $meany+$y[$i];

}

######mean of x

$meanx = $meanx/$points;

######mean of y

$meany = $meany/$points;

######linear regression terms

$ssxy = $points*$sxy-(($sx*$sy));

$ssx = $points*$sx2-($sx*$sx);

$ssy = $points*$sy2-($sy*$sy);

########linear regression calculation

$r = sprintf("%0.5f",$ssxy/sqrt($ssx*$ssy));

$r2 = sprintf("%0.3f",$r*$r);

$b1 = sprintf("%0.4f",$ssxy/$ssx);

$b0 = sprintf("%0.4f",$meany-$b1*$meanx);

######quadratic regression terms

$qa = (($points*$sx2y- $sx2*$sy)*($points*$sx2 -$sx*$sx)-

      ($points*$sxy-$sx*$sy)*($points*$sx3 -$sx*$sx2))/

      (($points*$sx2 -$sx*$sx)*($points*$sx4 -($sx2*$sx2))-

      ($points*$sx3-$sx*$sx2)*($points*$sx3-$sx*$sx2));

$a = sprintf("%0.4f",$qa); 

$qb = (-($points*$sx2y- $sx2*$sy)*($points*$sx3-$sx*$sx2)+

      ($points*$sxy-$sx*$sy)*($points*$sx4 -($sx2*$sx2)))/

      (($points*$sx2 -$sx*$sx)*($points*$sx4 -($sx2*$sx2))-

      ($points*$sx3-$sx*$sx2)*($points*$sx3-$sx*$sx2));

$b = sprintf("%0.4f",$qb);      

$qc = ($sy/$points)-$qb*($sx/$points)-$qa*($sx2/$points);

$c = sprintf("%0.4f",$qc);    

######for quadratic r^2

for($i=0; $i<$points; $i++) {

######for SST

    $sst = $sst + ($y[$i]-$meany)*($y[$i]-$meany);

#####for SSE

    $sse = $sse + ($y[$i]-$qa*$x[$i]*$x[$i] -$qb*$x[$i] -$qc)*($y[$i]-$qa*$x[$i]*$x[$i] -$qb*$x[$i] -$qc);

}

$qr = sprintf("%0.3f",1-($sse/$sst));

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


####multianswer

Context()->strings->add("no solution"=>{},

  "no solutions"=>{alias=>'no solution'}, 

  "none"=>{alias=>'no solution'});

  

Context()->strings->add("linear"=>{});

Context()->strings->add("exponential"=>{});

Context()->strings->add("logarithmic"=>{});

Context()->strings->add("logistic"=>{});

Context()->strings->add("quadratic"=>{});


$ans_5 = PopUp(["select","linear","quadratic","exponential","logistic","logarithmic"], "logarithmic");

$ans_6 = $b0 + $b1*($year-1970);

$ans_7 = ($mpg-$b0)/($b1);


$multians = MultiAnswer($ans_5, $ans_6, $ans_7)->with(

  singleResult => 0, allowBlankAnswers => 1,

  checker => sub {

      my ( $correct, $student, $self ) = @_;

      my ( $a1s, $a2s, $a3s ) = @{$student};

      my ( $a1, $a2, $a3 ) = @{$correct};

      if ( $a1s->value == "linear"){ 

            if ($a2s == $b0+$b1*($year-1970) && $a3s == ($mpg-$b0)/$b1) {$self->setMessage(1,"A line is not the best choice.");

  return [1,1,1]}

            elsif ($a2s == $b0+$b1*($year-1970) && $a3s != ($mpg-$b0)/$b1) {$self->setMessage(1,"A line is not the best choice.");

            $self->setMessage(3,"Check your calculation.");

  return [1,1,0]}

            elsif ($a2s != $b0+$b1*($year-1970) && $a3s == ($mpg-$b0)/$b1) {$self->setMessage(1,"A line is not the best choice.");

            $self->setMessage(2,"Check your calculation.");

  return [1,0,1]}

            else {$self->setMessage(1,"A line is not the best choice.");

            $self->setMessage(2,"Check your calculation.");

            $self->setMessage(3,"Check your calculation.");

            return [1,0,0]}}

      elsif ( $a1s->value == "quadratic"){ 

            if ($a2s == $a*($year-1970)**2 +$b*($year-1970) +$c && $a3s == "no solution") {

  return [1,1,1]}

            elsif ($a2s == $a*($year-1970)**2 +$b*($year-1970) +$c && $a3s != "no solution") {$self->setMessage(3,"Check your calculation.");

  return [1,1,0]}

            elsif ($a2s != $a*($year-1970)**2 +$b*($year-1970) +$c && $a3s == "no solution") {$self->setMessage(2,"Check your calculation.");

  return [1,0,1]}

            else {$self->setMessage(2,"Check your calculation.");

            $self->setMessage(3,"Check your calculation.");

            return [1,0,0]}}

        elsif ( $a1s->value == "exponential"){ 

            if ($a2s == 15.3285*(1.0107**($year-1970)) && $a3s == ln($mpg/15.3285)/ln(1.0107)) {$self->setMessage(1,"A exponential is not a good choice.");

  return [0,1,1]}

            elsif ($a2s == 15.3285*(1.0107**($year-1970)) && $a3s != ln($mpg/15.3285)/ln(1.0107)) {$self->setMessage(1,"A exponental is not a good choice.");

$self->setMessage(3,"Check your calculation.");

  return [0,1,0]}

            elsif ($a2s != 15.3285*(1.0107**($year-1970)) && $a3s == ln($mpg/15.3285)/ln(1.0107)) {$self->setMessage(1,"A exponential is not a good choice.");

$self->setMessage(2,"Check your calculation.");

  return [0,0,1]}

            else {$self->setMessage(1,"A exponential is not a good choice.");

            $self->setMessage(2,"Check your calculation.");

            $self->setMessage(3,"Check your calculation.");

            return [0,0,0]}}

        elsif ( $a1s->value == "logistic"){ 

            if ($a2s == 24.2704/(1+1.2059*exp(-0.08638*($year-1970))) && $a3s == "no solution") {

  return [1,1,1]}

            elsif ($a2s == 24.2704/(1+1.2059*exp(-0.08638*($year-1970))) && $a3s != "no solution") {$self->setMessage(3,"Check your calculation.");

  return [1,1,0]}

            elsif ($a2s != 24.2704/(1+1.2059*exp(-0.08638*($year-1970))) && $a3s == "no solution") {$self->setMessage(2,"Check your calculation.");

  return [1,0,1]}

            else {$self->setMessage(2,"Check your calculation.");

            $self->setMessage(3,"Check your calculation.");

            return [1,0,0]}}

        elsif ( $a1s->value == "logarithmic"){ 

            if ($a2s == 4.3528+5.1643*ln(($year-1970)) && $a3s == exp(($mpg-4.3528)/5.1643)) {

  return [1,1,1]}

            elsif ($a2s == 4.3528+5.1643*ln(($year-1970)) && $a3s != exp(($mpg-4.3528)/5.1643)) {$self->setMessage(3,"Check your calculation.");

  return [1,1,0]}

            elsif ($a2s != 4.3528+5.1643*ln(($year-1970)) && $a3s == exp(($mpg-4.3528)/5.1643)) {$self->setMessage(2,"Check your calculation.");

  return [1,0,1]}

            else {$self->setMessage(2,"Check your calculation.");

            $self->setMessage(3,"Check your calculation.");

            return [1,0,0]}}

       else {

              return [0,0,0];

          }

      }

);

  

#  Main

BEGIN_TEXT

$BBOLD Note: The problem covers problems 1-5 from Section 5.5 of College Algebra an Applied Approach. $EBOLD

$PAR

$BBOLD Note on Rounding: Your answers are dependent on rounding. Be sure to round as the problem specifies. $EBOLD

$PAR

$BR

The following questions use the following information from the U.S. Department

of Transportation.

$BR

\{begintable(2)\}

\{row("Years after 1970", "Avg. Number of MPG for U.S. Automobiles (light duty)")\}

\{row("\($x[0]\)", "\($y[0]\)")\}

\{row("\($x[1]\)", "\($y[1]\)")\}

\{row("\($x[2]\)", "\($y[2]\)")\}

\{row("\($x[3]\)", "\($y[3]\)")\}

\{row("\($x[4]\)", "\($y[4]\)")\}

\{endtable()\}

 $BR

(a) Find the linear , quadratic, exponential, logistic, and logarithmic regression models that gives the miles per gallon as a function of years after 1970. (Round answers to four decimal places for the regression and 3 decimal places for the \(r^2\).)

$PAR

Linear: \(y = \) \{ans_rule(15)\}  with \(r^2 = \) \{ans_rule(15)\}. 

 $PAR

$BR

Quadratic: \(y = \) \{ans_rule(15)\} with \(r^2 = \) \{ans_rule(15)\}. 

 $PAR

$BR

Exponential: \(y = \) \{ans_rule(15)\} with \(r^2 = \) \{ans_rule(15)\}. 

$PAR

$BR

Logistic: \(y = \) \{ans_rule(15)\}. 

$PAR

$BR

Logarithmic: \(y = \) \{ans_rule(15)\} with \(r^2 = \) \{ans_rule(15)\}. 

$PAR

$BR

$BR

b) Which of the better model to use? 

$Par

$BR

The best model to use is \{$multians->menu()\}

$PAR

$BR

$BR

c) For the model chosen in the last part, what is the average miles per gallon expected to be in $year? (Round to 1 decimal place.)

$BR

The average miles per gallon in $year is predicted to be \{$multians->ans_rule(15)\} mpg.

$PAR

$BR

$BR

d) For the model chosen, when will the miles per gallon be $mpg? (Depending on your, choice you may have no solution or very large numbers. Round any decimals to one place.)

$BR 

We predict that the mpg will be $mpg \{$multians->ans_rule(15)\} years after 1970.

END_TEXT


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

#  Answers

$showPartialCorrectAnswers = 1;

$ans_1 = "$b0+$b1*x";

ANS(fun_cmp($ans_1,tolType => 'absolute',

  tolerance => .002));

$ans_2 = Compute($r2)->with(tolType=>'absolute', tolerance=>'0.002');

  ANS($ans_2->cmp->withPostFilter(AnswerHints(

           sub {

                my ($correct,$student,$anshash) = @_;

                return abs($student-$correct) < .01;

                } => ["Your answer is close.  Try the calculation using more accuracy."])));                       

$ans_3 = "$c + $b*x +$a*x^2";

ANS(fun_cmp($ans_3,tolType => 'absolute',

  tolerance => .0002));

$ans_4 = Compute($qr)->with(tolType=>'absolute', tolerance=>'0.002');

  ANS($ans_4->cmp->withPostFilter(AnswerHints(

           sub {

                my ($correct,$student,$anshash) = @_;

                return abs($student-$correct) < .01;

                } => ["Your answer is close.  Try the calculation using more accuracy."])));

$ans_exp = "15.3285*(1.0107)^x";

$ans_expr2 = Compute(0.891)->with(tolType=>'absolute', tolerance=>'0.002');

ANS(fun_cmp($ans_exp,tolType => 'absolute',

  tolerance => .0002));

  ANS($ans_expr2->cmp->withPostFilter(AnswerHints(

           sub {

                my ($correct,$student,$anshash) = @_;

                return abs($student-$correct) < .01;

                } => ["Your answer is close.  Try the calculation using more accuracy."])));

$ans_logis = "24.2704/(1 + 1.2059*e^(-0.08638*x))";

ANS(fun_cmp($ans_logis,tolType => 'absolute',

  tolerance => .0002));

$ans_ln = "4.3528+5.1643*ln(x)";

$ans_lnr2 = Compute(0.992)->with(tolType=>'absolute', tolerance=>'0.002');

ANS(fun_cmp($ans_ln,tolType => 'absolute',

  tolerance => .0002));

  ANS($ans_lnr2->cmp->withPostFilter(AnswerHints(

           sub {

                my ($correct,$student,$anshash) = @_;

                return abs($student-$correct) < .01;

                } => ["Your answer is close.  Try the calculation using more accuracy."])));              

ANS($multians->cmp()); 

ENDDOCUMENT();       # This should be the last executable line in the problem.


In reply to Gregory Varner

Re: Answer dependent on student response

by Glenn Rice -

It is a lot easier for someone to look at your code and help you if you post it as an attachment instead of cutting pasting it into your post.

In reply to Glenn Rice

Re: Answer dependent on student response

by Gregory Varner -
That makes sense. Sorry about that. I am unsure the best file format to do so I did a word document. I am writing the problems through the Edfinity interface and did not detect an easy way to save the question file.
In reply to Gregory Varner

Re: Answer dependent on student response

by Glenn Rice -

Here are some of the problems that need to be resolved.

First, you are trying to compare strings using "==".  In Perl that needs to be "eq" instead.

Next, you are using the old style fun_cmp with the MathObjects version of the "tolerance" argument.  For fun_cmp it is just "tol".

Also, to put the PopUp menu in when it is part of a MultiAnswer object use $multians->ans_rule(), not $multians->menu().

This at least takes care of the warnings.