General Solution to a Differential Equation

Use a custom answer checkers for ODEs to determine the general solution of a Differential Equation

Complete Code

Download file: GeneralSolutionODE.pg

POD for Macro Files

PG problem file

Explanation

DOCUMENT();

loadMacros('PGstandard.pl', 'PGML.pl', 'parserAssignment.pl', 'PGcourse.pl');

Preamble

We load parserAssignment.pl to require student answers to be of the form y = ....

Context()->variables->add(
    c1 => 'Real',
    c2 => 'Real',
    c3 => 'Real',
    y  => 'Real',
);
Context()->flags->set(
    formatStudentAnswer     => 'parsed',
    reduceConstants         => 0,
    reduceConstantFunctions => 0,
);
parser::Assignment->Allow;

$a = list_random(2, 3, 5, 6, 7, 8);

# The characteristic polynomial is (r - 1)(r^2 + $a).

$answer = Compute("y = c1 e^x + c2 cos(sqrt($a) x) + c3 sin(sqrt($a) x)");

$cmp = $answer->cmp(
    checker => sub {

        my ($correct, $student, $answerHash) = @_;
        my $stu = Formula($student->{tree}{rop});

        #  Check for arbitrary constants
        Value->Error("Is your answer the most general solution?")
            if (Formula($stu->D('c1')) == Formula(0)
                || Formula($stu->D('c2')) == Formula(0)
                || Formula($stu->D('c3')) == Formula(0));

        #  Linear independence (Wronskian)
        my $x = Real(1.43);

        my $a11 =
            $stu->eval('c1' => 1, 'c2' => 0, 'c3' => 0, x => $x, y => 0);
        my $a12 =
            $stu->eval('c1' => 0, 'c2' => 1, 'c3' => 0, x => $x, y => 0);
        my $a13 =
            $stu->eval('c1' => 0, 'c2' => 0, 'c3' => 1, x => $x, y => 0);

        my $a21 = $stu->D('x')
            ->eval('c1' => 1, 'c2' => 0, 'c3' => 0, x => $x, y => 0);
        my $a22 = $stu->D('x')
            ->eval('c1' => 0, 'c2' => 1, 'c3' => 0, x => $x, y => 0);
        my $a23 = $stu->D('x')
            ->eval('c1' => 0, 'c2' => 0, 'c3' => 1, x => $x, y => 0);

        my $a31 = $stu->D('x', 'x')
            ->eval('c1' => 1, 'c2' => 0, 'c3' => 0, x => $x, y => 0);
        my $a32 = $stu->D('x', 'x')
            ->eval('c1' => 0, 'c2' => 1, 'c3' => 0, x => $x, y => 0);
        my $a33 = $stu->D('x', 'x')
            ->eval('c1' => 0, 'c2' => 0, 'c3' => 1, x => $x, y => 0);

        Value->Error(
            'Your functions are not linearly independent or your answer is not complete'
            )
            if (
                (
                    $a11 * ($a22 * $a33 - $a32 * $a23) +
                    $a13 * ($a21 * $a32 - $a31 * $a22)
                ) == ($a12 * ($a21 * $a33 - $a31 * $a23))
            );

        #  Check that the student answer is a solution to the DE
        my $stu1 = Formula($stu->D('x'));
        my $stu2 = Formula($stu->D('x', 'x'));
        my $stu3 = Formula($stu->D('x', 'x', 'x'));
        return ($stu3 + $a * $stu1) == ($stu2 + $a * $stu);

    }
);

Setup

Add the arbitrary constants c1, c2, and c3 to the context as variables so that they can be used in evaluations.

Use parser::Assignment->Allow to allow equation answers of the form y = .... See parserAssignment.pl for additional information.

In the checker my $stu = Formula($student->{tree}{rop}); is used to get the right side of the assignment in the student answer (to get the left side of the assignment use lop). Use Formula($stu->D('c1')) == Formula(0) to verify that the student answer uses the variable c1.

Substitute numerical values for the variables c1, c2, and c3 and apply the Wronskian test for independence. Note that zero level tolerance in WeBWorK is much more stringent that non-zero level tolerance. So the terms of the Wronskian equation are rearranged so that there are nonzero terms on both sides of the equation to give a more reliable check.

Finally, several derivatives of the student answer are computed and used to check that the student answer satisfies the differential equation. Again, to check that differential equation, the terms are rearanged to have nonzero terms on both sides, in order to give a more reliable check.

BEGIN_PGML
Find the general solution to
[`y^{\,\prime\prime\prime} - y^{\,\prime\prime} + [$a] y^{\,\prime} - [$a] y = 0`].

In your answer, use [`c_1`], [`c_2`] and [`c_3`] to denote arbitrary constants
and [`x`] the independent variable.  Your answer should be an equation of the
form [`y = \ldots`] and you should enter [`c_1`] as [|c1|]*,
[`c_2`] as [|c2|]*, and [`c_3`] as [|c3|]*.

[_]{$cmp}{30}
END_PGML

Statement

Give students detailed instructions about the format of the answer that is expected.

BEGIN_PGML_SOLUTION
Solution explanation goes here.
END_PGML_SOLUTION

ENDDOCUMENT();

Solution

A solution should be provided here.