Skip to main content
Logo image

Section 16 Dynamic Exercises

View Source for section
<section xml:id="section-dynamic-exercises">
  <title>Dynamic Exercises</title>
  <introduction>
    <p>
      This section demonstrates the use of dynamic randomized exercises built upon the framework of Runestone components.
      These demonstration problems incorporate a library supporting mathematical expressions both for varying the content of the statement of the exercises as well as the checking of submitted answers.
    </p>
  </introduction>
  <exercises>
    <title>Dynamic Fill-In</title>
    <introduction>
      <p>
        The first problem illustrates revised markup for fill-in problems that don't involve randomization and use simple string and number comparison tests.
        Later exercises illustrate the use of dynamically generated mathematical expressions.
      </p>
    </introduction>
    <exercise label="fillin-string-integer-new">
      <title>Fill-In, String and Number Answers</title>
      <statement>
        <p>
          Complete the following line of a Python program so that it will declare an integer variable <c>age</c> with an initial value of <c>5</c>.
        </p>
        <p>
          <fillin mode="string" answer="int" /> <c>age = </c> <fillin mode="number" answer="5" /><c>;</c>
        </p>
      </statement>
      <evaluation>
      <evaluate>
      <test>
      <strcmp use-answer="yes" />
      <feedback>
        <p>
          A variable of type <c>int</c> is appropriate for whole number ages.
        </p>
      </feedback>
      </test>
      <test>
      <strcmp>.*</strcmp>
      <feedback>
        <p>
          Remember that Java uses just the first three letters of the word
          <q>integer</q>
          to define an integral type.
        </p>
      </feedback>
      </test>
      </evaluate>
      <evaluate>
      <test>
      <numcmp use-answer="yes" />
      <feedback>
        <p>
          An integer variable may be initialized to a value.
        </p>
      </feedback>
      </test>
      <test>
      <strcmp>.*</strcmp>
      <feedback>
        <p>
          Use <c>5</c> as the initial value of the variable.
        </p>
      </feedback>
      </test>
      </evaluate>
      </evaluation>
    </exercise>
    <exercise label="dynamic-fitb-simple-formula">
      <title>Fill-In Formula (Dynamic)</title>
      <statement>
        <p>
          Find a formula for a cubic function <m>f(x)</m> that roots at <m>x=<eval obj="x1" /></m>,
          <m>x=<eval obj="x2" /></m>,
          and <m>x=<eval obj="x3" /></m> and so that <m>f(0)=<eval obj="y0" /></m>.
        </p>
        <p>
          <m>f(x)=</m> <fillin name="st_cubic" mode="math" ansobj="cubic" />
        </p>
      </statement>
      <solution>
        <p>
          Knowing the roots of a polynomial allows us to write down the formula of <m>f(x)</m> in factored form,
          <me>
            f(x) = A <eval obj="base_cubic" />
          </me>
          with an unknown scaling multiple <m>A</m>.
        </p>
        <p>
          When we evaluate <m>f(x)</m> at <m>x=0</m> using this formula, we find
          <me>
            f(0) = <eval obj="base_yint" />A
          </me>.
          Since we also know <m>f(0)=<eval obj="y0" /></m>,
          we can write down the equation
          <me>
            A <eval obj="base_cubic" /> = <eval obj="y0" />
          </me>
          and find that <m>A=<eval obj="A" /></m>.
        </p>
        <p>
          Consequently, we can write our function in the form
          <me>
            f(x)=<eval obj="cubic" />
          </me>.
        </p>
      </solution>
      <setup seed="314159">
        <de-object name="y0" context="number">
        <de-random distribution="discrete" min="-8" max="8" by="1" nonzero="yes" />
        </de-object>
        <de-object name="x1" context="number">
        <de-random distribution="discrete" min="-8" max="-4" by="1" />
        </de-object>
        <de-object name="d1" context="number">
        <de-random distribution="discrete" min="1" max="4" by="1" />
        </de-object>
        <de-object name="d2" context="number">
        <de-random distribution="discrete" min="1" max="4" by="1" />
        </de-object>
        <de-object name="x2" context="number">
        <de-number>x1+d1</de-number>
        </de-object>
        <de-object name="x3" context="number">
        <de-number>x2+d2</de-number>
        </de-object>
        <de-object name="base_cubic" context="formula">
        <de-expression reduce="yes">(x-x1)*(x-x2)*(x-x3)</de-expression>
        </de-object>
        <de-object name="base_yint" context="number">
        <de-evaluate>
        <formula><eval obj="base_cubic" /></formula>
        <variable name="x">0</variable>
        </de-evaluate>
        </de-object>
        <de-object name="A" context="number">
        <de-number reduce="yes">y0/base_yint</de-number>
        </de-object>
        <de-object name="cubic" context="formula">
        <de-expression reduce="yes">A*(x-x1)*(x-x2)*(x-x3)</de-expression>
        </de-object>
      </setup>
      <evaluation>
      <evaluate name="st_cubic">
      <test correct="yes">
      <mathcmp obj="cubic" />
      </test>
      </evaluate>
      </evaluation>
    </exercise>
    <exercise label="function-decomposition">
      <title>Decompose the Function</title>
      <statement>
        <p>
          Consider the function
          <me>
            h(x)=<eval obj="composition" />
          </me>.
          Find two nontrivial functions <m>f(x)</m> and <m>g(x)</m> so that <m>h(x) = f(g(x))</m>.
        </p>
        <p>
          <m>f(x) = </m> <fillin width="15" mode="math" ansobj="outerFormula" name="fGiven" /> and <m>g(x)=</m> <fillin width="15" mode="math" ansobj="innerFormula" name="gGiven" />
        </p>
      </statement>
      <solution>
        <p>
          Noticing that the expression <m><eval obj="innerFormula" /></m> appears inside parentheses with a power,
          it makes sense to think of that as the inner function,
          defining <m>g(x) = <eval obj="innerFormula" /></m>.
          The outer function describes what happens to that.
          If we imagined replacing the formula <m><eval obj="innerFormula" /></m> with a box and then call that box our variable <m>x</m>,
          we find the outer function is given by <m>f(x) = <eval obj="outerFormula" /></m>.
        </p>
        <p>
          This is not the only non-trivial composition.
          Can you find others?
        </p>
      </solution>
      <setup seed="4321">
        <de-object name="a" context="number">
        <de-random distribution="discrete" min="-4" max="5" by="1" nonzero="yes" />
        </de-object>
        <de-object name="n" context="number">
        <de-random distribution="discrete" min="2" max="5" />
        </de-object>
        <de-object name="b" context="number">
        <de-random distribution="discrete" min="-10" max="10" by="1" nonzero="yes" />
        </de-object>
        <de-object name="c" context="number">
        <de-random distribution="discrete" min="-4" max="5" by="1" nonzero="yes" />
        </de-object>
        <de-object name="d" context="number">
        <de-random distribution="discrete" min="-10" max="10" by="1" nonzero="yes" />
        </de-object>
        <de-object name="outerFormula" context="formula">
        <de-expression>a*x^n+b</de-expression>
        </de-object>
        <de-object name="innerFormula" context="formula">
        <de-expression>c*x+d</de-expression>
        </de-object>
        <de-object name="identityFunction" context="formula">
        <de-expression>x</de-expression>
        </de-object>
        <de-object name="composition" context="formula">
        <de-expression mode="substitution" reduce="yes">
        <formula><eval obj="outerFormula" /></formula>
        <variable name="x"><eval obj="innerFormula" /></variable>
        </de-expression>
        </de-object>
      </setup>
      <evaluation answers-coupled="yes">
      <evaluate name="fGiven">
      <test>
      <mathcmp obj="identityFunction" />
      <feedback>
        <p>
          <m>f(x)=x</m> is not allowed for nontrivial compositions.
        </p>
      </feedback>
      </test>
      <test>
      <logic op="and">
      <logic op="not">
      <mathcmp>
      <eval obj="composition" />
      <de-expression context="formula" mode="substitution">
      <formula><eval obj="fGiven" /></formula>
      <variable name="x"><eval obj="gGiven" /></variable>
      </de-expression>
      </mathcmp>
      </logic>
      <mathcmp>
      <eval obj="composition" />
      <de-expression context="formula" mode="substitution">
      <formula><eval obj="gGiven" /></formula>
      <variable name="x"><eval obj="fGiven" /></variable>
      </de-expression>
      </mathcmp>
      </logic>
      <feedback>
        <p>
          You have composed in the wrong order.
        </p>
      </feedback>
      </test>
      </evaluate>
      <evaluate name="gGiven">
      <test>
      <mathcmp obj="identityFunction" />
      <feedback>
        <p>
          <m>g(x)=x</m> is not allowed for nontrivial compositions.
        </p>
      </feedback>
      </test>
      </evaluate>
      <evaluate all="yes">
      <test correct="yes">
      <logic op="and">
      <mathcmp>
      <eval obj="composition" />
      <de-expression context="formula" mode="substitution">
      <formula><eval obj="fGiven" /></formula>
      <variable name="x"><eval obj="gGiven" /></variable>
      </de-expression>
      </mathcmp>
      <logic op="not">
      <mathcmp>
      <eval obj="fGiven" />
      <eval obj="identityFunction" />
      </mathcmp>
      </logic>
      <logic op="not">
      <mathcmp>
      <eval obj="gGiven" />
      <eval obj="identityFunction" />
      </mathcmp>
      </logic>
      </logic>
      </test>
      </evaluate>
      </evaluation>
    </exercise>
  </exercises>
</section>
This section demonstrates the use of dynamic randomized exercises built upon the framework of Runestone components. These demonstration problems incorporate a library supporting mathematical expressions both for varying the content of the statement of the exercises as well as the checking of submitted answers.

Exercises Dynamic Fill-In

View Source for exercises
<exercises>
  <title>Dynamic Fill-In</title>
  <introduction>
    <p>
      The first problem illustrates revised markup for fill-in problems that don't involve randomization and use simple string and number comparison tests.
      Later exercises illustrate the use of dynamically generated mathematical expressions.
    </p>
  </introduction>
  <exercise label="fillin-string-integer-new">
    <title>Fill-In, String and Number Answers</title>
    <statement>
      <p>
        Complete the following line of a Python program so that it will declare an integer variable <c>age</c> with an initial value of <c>5</c>.
      </p>
      <p>
        <fillin mode="string" answer="int" /> <c>age = </c> <fillin mode="number" answer="5" /><c>;</c>
      </p>
    </statement>
    <evaluation>
    <evaluate>
    <test>
    <strcmp use-answer="yes" />
    <feedback>
      <p>
        A variable of type <c>int</c> is appropriate for whole number ages.
      </p>
    </feedback>
    </test>
    <test>
    <strcmp>.*</strcmp>
    <feedback>
      <p>
        Remember that Java uses just the first three letters of the word
        <q>integer</q>
        to define an integral type.
      </p>
    </feedback>
    </test>
    </evaluate>
    <evaluate>
    <test>
    <numcmp use-answer="yes" />
    <feedback>
      <p>
        An integer variable may be initialized to a value.
      </p>
    </feedback>
    </test>
    <test>
    <strcmp>.*</strcmp>
    <feedback>
      <p>
        Use <c>5</c> as the initial value of the variable.
      </p>
    </feedback>
    </test>
    </evaluate>
    </evaluation>
  </exercise>
  <exercise label="dynamic-fitb-simple-formula">
    <title>Fill-In Formula (Dynamic)</title>
    <statement>
      <p>
        Find a formula for a cubic function <m>f(x)</m> that roots at <m>x=<eval obj="x1" /></m>,
        <m>x=<eval obj="x2" /></m>,
        and <m>x=<eval obj="x3" /></m> and so that <m>f(0)=<eval obj="y0" /></m>.
      </p>
      <p>
        <m>f(x)=</m> <fillin name="st_cubic" mode="math" ansobj="cubic" />
      </p>
    </statement>
    <solution>
      <p>
        Knowing the roots of a polynomial allows us to write down the formula of <m>f(x)</m> in factored form,
        <me>
          f(x) = A <eval obj="base_cubic" />
        </me>
        with an unknown scaling multiple <m>A</m>.
      </p>
      <p>
        When we evaluate <m>f(x)</m> at <m>x=0</m> using this formula, we find
        <me>
          f(0) = <eval obj="base_yint" />A
        </me>.
        Since we also know <m>f(0)=<eval obj="y0" /></m>,
        we can write down the equation
        <me>
          A <eval obj="base_cubic" /> = <eval obj="y0" />
        </me>
        and find that <m>A=<eval obj="A" /></m>.
      </p>
      <p>
        Consequently, we can write our function in the form
        <me>
          f(x)=<eval obj="cubic" />
        </me>.
      </p>
    </solution>
    <setup seed="314159">
      <de-object name="y0" context="number">
      <de-random distribution="discrete" min="-8" max="8" by="1" nonzero="yes" />
      </de-object>
      <de-object name="x1" context="number">
      <de-random distribution="discrete" min="-8" max="-4" by="1" />
      </de-object>
      <de-object name="d1" context="number">
      <de-random distribution="discrete" min="1" max="4" by="1" />
      </de-object>
      <de-object name="d2" context="number">
      <de-random distribution="discrete" min="1" max="4" by="1" />
      </de-object>
      <de-object name="x2" context="number">
      <de-number>x1+d1</de-number>
      </de-object>
      <de-object name="x3" context="number">
      <de-number>x2+d2</de-number>
      </de-object>
      <de-object name="base_cubic" context="formula">
      <de-expression reduce="yes">(x-x1)*(x-x2)*(x-x3)</de-expression>
      </de-object>
      <de-object name="base_yint" context="number">
      <de-evaluate>
      <formula><eval obj="base_cubic" /></formula>
      <variable name="x">0</variable>
      </de-evaluate>
      </de-object>
      <de-object name="A" context="number">
      <de-number reduce="yes">y0/base_yint</de-number>
      </de-object>
      <de-object name="cubic" context="formula">
      <de-expression reduce="yes">A*(x-x1)*(x-x2)*(x-x3)</de-expression>
      </de-object>
    </setup>
    <evaluation>
    <evaluate name="st_cubic">
    <test correct="yes">
    <mathcmp obj="cubic" />
    </test>
    </evaluate>
    </evaluation>
  </exercise>
  <exercise label="function-decomposition">
    <title>Decompose the Function</title>
    <statement>
      <p>
        Consider the function
        <me>
          h(x)=<eval obj="composition" />
        </me>.
        Find two nontrivial functions <m>f(x)</m> and <m>g(x)</m> so that <m>h(x) = f(g(x))</m>.
      </p>
      <p>
        <m>f(x) = </m> <fillin width="15" mode="math" ansobj="outerFormula" name="fGiven" /> and <m>g(x)=</m> <fillin width="15" mode="math" ansobj="innerFormula" name="gGiven" />
      </p>
    </statement>
    <solution>
      <p>
        Noticing that the expression <m><eval obj="innerFormula" /></m> appears inside parentheses with a power,
        it makes sense to think of that as the inner function,
        defining <m>g(x) = <eval obj="innerFormula" /></m>.
        The outer function describes what happens to that.
        If we imagined replacing the formula <m><eval obj="innerFormula" /></m> with a box and then call that box our variable <m>x</m>,
        we find the outer function is given by <m>f(x) = <eval obj="outerFormula" /></m>.
      </p>
      <p>
        This is not the only non-trivial composition.
        Can you find others?
      </p>
    </solution>
    <setup seed="4321">
      <de-object name="a" context="number">
      <de-random distribution="discrete" min="-4" max="5" by="1" nonzero="yes" />
      </de-object>
      <de-object name="n" context="number">
      <de-random distribution="discrete" min="2" max="5" />
      </de-object>
      <de-object name="b" context="number">
      <de-random distribution="discrete" min="-10" max="10" by="1" nonzero="yes" />
      </de-object>
      <de-object name="c" context="number">
      <de-random distribution="discrete" min="-4" max="5" by="1" nonzero="yes" />
      </de-object>
      <de-object name="d" context="number">
      <de-random distribution="discrete" min="-10" max="10" by="1" nonzero="yes" />
      </de-object>
      <de-object name="outerFormula" context="formula">
      <de-expression>a*x^n+b</de-expression>
      </de-object>
      <de-object name="innerFormula" context="formula">
      <de-expression>c*x+d</de-expression>
      </de-object>
      <de-object name="identityFunction" context="formula">
      <de-expression>x</de-expression>
      </de-object>
      <de-object name="composition" context="formula">
      <de-expression mode="substitution" reduce="yes">
      <formula><eval obj="outerFormula" /></formula>
      <variable name="x"><eval obj="innerFormula" /></variable>
      </de-expression>
      </de-object>
    </setup>
    <evaluation answers-coupled="yes">
    <evaluate name="fGiven">
    <test>
    <mathcmp obj="identityFunction" />
    <feedback>
      <p>
        <m>f(x)=x</m> is not allowed for nontrivial compositions.
      </p>
    </feedback>
    </test>
    <test>
    <logic op="and">
    <logic op="not">
    <mathcmp>
    <eval obj="composition" />
    <de-expression context="formula" mode="substitution">
    <formula><eval obj="fGiven" /></formula>
    <variable name="x"><eval obj="gGiven" /></variable>
    </de-expression>
    </mathcmp>
    </logic>
    <mathcmp>
    <eval obj="composition" />
    <de-expression context="formula" mode="substitution">
    <formula><eval obj="gGiven" /></formula>
    <variable name="x"><eval obj="fGiven" /></variable>
    </de-expression>
    </mathcmp>
    </logic>
    <feedback>
      <p>
        You have composed in the wrong order.
      </p>
    </feedback>
    </test>
    </evaluate>
    <evaluate name="gGiven">
    <test>
    <mathcmp obj="identityFunction" />
    <feedback>
      <p>
        <m>g(x)=x</m> is not allowed for nontrivial compositions.
      </p>
    </feedback>
    </test>
    </evaluate>
    <evaluate all="yes">
    <test correct="yes">
    <logic op="and">
    <mathcmp>
    <eval obj="composition" />
    <de-expression context="formula" mode="substitution">
    <formula><eval obj="fGiven" /></formula>
    <variable name="x"><eval obj="gGiven" /></variable>
    </de-expression>
    </mathcmp>
    <logic op="not">
    <mathcmp>
    <eval obj="fGiven" />
    <eval obj="identityFunction" />
    </mathcmp>
    </logic>
    <logic op="not">
    <mathcmp>
    <eval obj="gGiven" />
    <eval obj="identityFunction" />
    </mathcmp>
    </logic>
    </logic>
    </test>
    </evaluate>
    </evaluation>
  </exercise>
</exercises>
The first problem illustrates revised markup for fill-in problems that don’t involve randomization and use simple string and number comparison tests. Later exercises illustrate the use of dynamically generated mathematical expressions.

1. Fill-In, String and Number Answers.

View Source for exercise
<exercise label="fillin-string-integer-new">
  <title>Fill-In, String and Number Answers</title>
  <statement>
    <p>
      Complete the following line of a Python program so that it will declare an integer variable <c>age</c> with an initial value of <c>5</c>.
    </p>
    <p>
      <fillin mode="string" answer="int" /> <c>age = </c> <fillin mode="number" answer="5" /><c>;</c>
    </p>
  </statement>
  <evaluation>
  <evaluate>
  <test>
  <strcmp use-answer="yes" />
  <feedback>
    <p>
      A variable of type <c>int</c> is appropriate for whole number ages.
    </p>
  </feedback>
  </test>
  <test>
  <strcmp>.*</strcmp>
  <feedback>
    <p>
      Remember that Java uses just the first three letters of the word
      <q>integer</q>
      to define an integral type.
    </p>
  </feedback>
  </test>
  </evaluate>
  <evaluate>
  <test>
  <numcmp use-answer="yes" />
  <feedback>
    <p>
      An integer variable may be initialized to a value.
    </p>
  </feedback>
  </test>
  <test>
  <strcmp>.*</strcmp>
  <feedback>
    <p>
      Use <c>5</c> as the initial value of the variable.
    </p>
  </feedback>
  </test>
  </evaluate>
  </evaluation>
</exercise>

2. Fill-In Formula (Dynamic).

View Source for exercise
<exercise label="dynamic-fitb-simple-formula">
  <title>Fill-In Formula (Dynamic)</title>
  <statement>
    <p>
      Find a formula for a cubic function <m>f(x)</m> that roots at <m>x=<eval obj="x1" /></m>,
      <m>x=<eval obj="x2" /></m>,
      and <m>x=<eval obj="x3" /></m> and so that <m>f(0)=<eval obj="y0" /></m>.
    </p>
    <p>
      <m>f(x)=</m> <fillin name="st_cubic" mode="math" ansobj="cubic" />
    </p>
  </statement>
  <solution>
    <p>
      Knowing the roots of a polynomial allows us to write down the formula of <m>f(x)</m> in factored form,
      <me>
        f(x) = A <eval obj="base_cubic" />
      </me>
      with an unknown scaling multiple <m>A</m>.
    </p>
    <p>
      When we evaluate <m>f(x)</m> at <m>x=0</m> using this formula, we find
      <me>
        f(0) = <eval obj="base_yint" />A
      </me>.
      Since we also know <m>f(0)=<eval obj="y0" /></m>,
      we can write down the equation
      <me>
        A <eval obj="base_cubic" /> = <eval obj="y0" />
      </me>
      and find that <m>A=<eval obj="A" /></m>.
    </p>
    <p>
      Consequently, we can write our function in the form
      <me>
        f(x)=<eval obj="cubic" />
      </me>.
    </p>
  </solution>
  <setup seed="314159">
    <de-object name="y0" context="number">
    <de-random distribution="discrete" min="-8" max="8" by="1" nonzero="yes" />
    </de-object>
    <de-object name="x1" context="number">
    <de-random distribution="discrete" min="-8" max="-4" by="1" />
    </de-object>
    <de-object name="d1" context="number">
    <de-random distribution="discrete" min="1" max="4" by="1" />
    </de-object>
    <de-object name="d2" context="number">
    <de-random distribution="discrete" min="1" max="4" by="1" />
    </de-object>
    <de-object name="x2" context="number">
    <de-number>x1+d1</de-number>
    </de-object>
    <de-object name="x3" context="number">
    <de-number>x2+d2</de-number>
    </de-object>
    <de-object name="base_cubic" context="formula">
    <de-expression reduce="yes">(x-x1)*(x-x2)*(x-x3)</de-expression>
    </de-object>
    <de-object name="base_yint" context="number">
    <de-evaluate>
    <formula><eval obj="base_cubic" /></formula>
    <variable name="x">0</variable>
    </de-evaluate>
    </de-object>
    <de-object name="A" context="number">
    <de-number reduce="yes">y0/base_yint</de-number>
    </de-object>
    <de-object name="cubic" context="formula">
    <de-expression reduce="yes">A*(x-x1)*(x-x2)*(x-x3)</de-expression>
    </de-object>
  </setup>
  <evaluation>
  <evaluate name="st_cubic">
  <test correct="yes">
  <mathcmp obj="cubic" />
  </test>
  </evaluate>
  </evaluation>
</exercise>

3. Decompose the Function.

View Source for exercise
<exercise label="function-decomposition">
  <title>Decompose the Function</title>
  <statement>
    <p>
      Consider the function
      <me>
        h(x)=<eval obj="composition" />
      </me>.
      Find two nontrivial functions <m>f(x)</m> and <m>g(x)</m> so that <m>h(x) = f(g(x))</m>.
    </p>
    <p>
      <m>f(x) = </m> <fillin width="15" mode="math" ansobj="outerFormula" name="fGiven" /> and <m>g(x)=</m> <fillin width="15" mode="math" ansobj="innerFormula" name="gGiven" />
    </p>
  </statement>
  <solution>
    <p>
      Noticing that the expression <m><eval obj="innerFormula" /></m> appears inside parentheses with a power,
      it makes sense to think of that as the inner function,
      defining <m>g(x) = <eval obj="innerFormula" /></m>.
      The outer function describes what happens to that.
      If we imagined replacing the formula <m><eval obj="innerFormula" /></m> with a box and then call that box our variable <m>x</m>,
      we find the outer function is given by <m>f(x) = <eval obj="outerFormula" /></m>.
    </p>
    <p>
      This is not the only non-trivial composition.
      Can you find others?
    </p>
  </solution>
  <setup seed="4321">
    <de-object name="a" context="number">
    <de-random distribution="discrete" min="-4" max="5" by="1" nonzero="yes" />
    </de-object>
    <de-object name="n" context="number">
    <de-random distribution="discrete" min="2" max="5" />
    </de-object>
    <de-object name="b" context="number">
    <de-random distribution="discrete" min="-10" max="10" by="1" nonzero="yes" />
    </de-object>
    <de-object name="c" context="number">
    <de-random distribution="discrete" min="-4" max="5" by="1" nonzero="yes" />
    </de-object>
    <de-object name="d" context="number">
    <de-random distribution="discrete" min="-10" max="10" by="1" nonzero="yes" />
    </de-object>
    <de-object name="outerFormula" context="formula">
    <de-expression>a*x^n+b</de-expression>
    </de-object>
    <de-object name="innerFormula" context="formula">
    <de-expression>c*x+d</de-expression>
    </de-object>
    <de-object name="identityFunction" context="formula">
    <de-expression>x</de-expression>
    </de-object>
    <de-object name="composition" context="formula">
    <de-expression mode="substitution" reduce="yes">
    <formula><eval obj="outerFormula" /></formula>
    <variable name="x"><eval obj="innerFormula" /></variable>
    </de-expression>
    </de-object>
  </setup>
  <evaluation answers-coupled="yes">
  <evaluate name="fGiven">
  <test>
  <mathcmp obj="identityFunction" />
  <feedback>
    <p>
      <m>f(x)=x</m> is not allowed for nontrivial compositions.
    </p>
  </feedback>
  </test>
  <test>
  <logic op="and">
  <logic op="not">
  <mathcmp>
  <eval obj="composition" />
  <de-expression context="formula" mode="substitution">
  <formula><eval obj="fGiven" /></formula>
  <variable name="x"><eval obj="gGiven" /></variable>
  </de-expression>
  </mathcmp>
  </logic>
  <mathcmp>
  <eval obj="composition" />
  <de-expression context="formula" mode="substitution">
  <formula><eval obj="gGiven" /></formula>
  <variable name="x"><eval obj="fGiven" /></variable>
  </de-expression>
  </mathcmp>
  </logic>
  <feedback>
    <p>
      You have composed in the wrong order.
    </p>
  </feedback>
  </test>
  </evaluate>
  <evaluate name="gGiven">
  <test>
  <mathcmp obj="identityFunction" />
  <feedback>
    <p>
      <m>g(x)=x</m> is not allowed for nontrivial compositions.
    </p>
  </feedback>
  </test>
  </evaluate>
  <evaluate all="yes">
  <test correct="yes">
  <logic op="and">
  <mathcmp>
  <eval obj="composition" />
  <de-expression context="formula" mode="substitution">
  <formula><eval obj="fGiven" /></formula>
  <variable name="x"><eval obj="gGiven" /></variable>
  </de-expression>
  </mathcmp>
  <logic op="not">
  <mathcmp>
  <eval obj="fGiven" />
  <eval obj="identityFunction" />
  </mathcmp>
  </logic>
  <logic op="not">
  <mathcmp>
  <eval obj="gGiven" />
  <eval obj="identityFunction" />
  </mathcmp>
  </logic>
  </logic>
  </test>
  </evaluate>
  </evaluation>
</exercise>