Kasper
Kasper

Reputation: 13622

Matching quotient function in maxima

We have an online platform where we use maxima on the backend to give feedback on the answers that the student give.

Say that the solution of a polynomial long division is the following function:

sol: 3+(2+4*x)/(3*x^2+2*x+8);

Let's say that the student gives the answer:

ans: 3 +(3-5*x)/(3x^2+2*x+8)

We then want to give feedback along the lines.

Your answer is indeed of the following form:

enter image description here

The constant s is correct, but you didn't choose the right linear function r(x).

I try to implement this feedback in the following way:

ans: 3 +(3-5*x)/(3x^2+2*x+8);
remvalue(a,b,c,d);
matchdeclare([a,b,c,d], constantp);
defmatch(match, d+ (a*x+b)/(3*x^2+2*x+8));
match(ans);

However, defmatch doesn't seem to be able to match this. Is there any other function I can use for matching quotient function like this?

It does work in more simple scenarios:

ans: (3-5*x)/(3*x^2+2*x+8); 
remvalue(a,b,c);
matchdeclare([a,b,c], constantp);     
defmatch(match, (a*x+b)/(3*x^2+2*x+8));     
match(ans);

Upvotes: 1

Views: 166

Answers (1)

Robert Dodier
Robert Dodier

Reputation: 17575

If the problems are all polynomial division, maybe you can use the divide function which returns the quotient and remainder and then verify that the student's input is the same as quotient + remainder/divisor.

As to matching quotient + remainder/divisor, defmatch might not be powerful enough because it is mostly (although not entirely) looking for formal matches, and it can't, in many cases, detect expressions which are equivalent but formally different.

Let me think about how to implement a match function for this problem. Perhaps others have a suggestion too.

EDIT: Here's a way to match such expressions. I'll separate a ratio of polynomials from other terms. If there is one ratio term, and all the other terms are a polynomial, then the pattern you want is matched.

I've made use of at least one obscure but useful and even comprehensible feature of matching of "+" expressions. Since "+" is commutative, the pattern matcher sweeps up all the arguments which match the first predicate that is attempted, then sweeps through with the second, and so, if there are more than two predicts. If any pattern matching variable is declared to match all, it matches all arguments and there are none left. The pattern variables will be attempted in reverse order, so aa will be processed last. The effect is to divide a "+" expression into terms which match a stated predicate and a catch-all for everything else. This is made use of in %i7.

(%i2) matchdeclare (pp, lambda ([e], polynomialp (e, [pvar]))) $
(%i3) matchdeclare (qq, lambda ([e], diff (e, pvar) # 0 and polynomialp (e, [pvar]))) $
(%i4) defmatch (match_pratio, pp/qq, pvar) $
(%i5) matchdeclare (aa, all) $
(%i6) matchdeclare (rr, lambda ([e], match_pratio (e, pvar) # false)) $
(%i7) defmatch (match_pratio_plus_remainder, rr + aa, pvar) $
(%i8) match_foo (e, pvar) := 
  block ([aa, pp, qq, rr],
    if match_pratio (e, pvar) # false
      then [0, pp, qq, pp/qq]
    elseif match_pratio_plus_remainder (e, pvar) # false
      then if polynomialp (aa, [pvar]) and op(rr) # "+"
        then [aa, pp, qq, rr]) $

Here are some examples that match:

(%i9) match_foo (u^2/2 - 3*u + 1 + (u - 1)/(u^2 + u - 1), u);
            2
           u                     2            u - 1
(%o9)     [-- - 3 u + 1, u - 1, u  + u - 1, ----------]
           2                                 2
                                            u  + u - 1
(%i10) match_foo (u^2/2 - 3*u + 1 - 2*(u - 1)/(u^2 + u - 1), u);
         2
        u                           2            2 (u - 1)
(%o10) [-- - 3 u + 1, - 2 (u - 1), u  + u - 1, - ----------]
        2                                         2
                                                 u  + u - 1
(%i11) match_foo (u^2/2 - 3*u + 1 - 2/(u^2 + u - 1), u);
            2
           u                   2                2
(%o11)    [-- - 3 u + 1, - 2, u  + u - 1, - ----------]
           2                                 2
                                            u  + u - 1
(%i12) match_foo (1 - 2/(u^2 + u - 1), u);
                         2                2
(%o12)         [1, - 2, u  + u - 1, - ----------]
                                       2
                                      u  + u - 1
(%i13) match_foo (- 2/(u^2 + u - 1), u);
                         2                2
(%o13)         [0, - 2, u  + u - 1, - ----------]
                                       2
                                      u  + u - 1

Here are some examples that don't match: two polynomial ratio terms, no polynomial ratio, and a nonpolynomial term.

(%i14) match_foo (1/u - 2/(u^2 + u - 1), u);
(%o14)                        false
(%i15) match_foo (1 - (u^2 + u - 1)/2, u);
(%o15)                        false
(%i16) match_foo (sin(u) - 2/(u^2 + u - 1), u);
(%o16)                        false

SECOND EDIT: I think I've misnamed match_pratio_plus_remainder, it should probably be match_remainder_plus_quotient. Oh well.

Upvotes: 2

Related Questions