<?xml version="1.0" encoding="UTF-8"?>
<quiz>
<!-- question: 15334  -->
  <question type="stack">
    <name>
      <text>Parsons problem with "if and only if" proof</text>
    </name>
    <questiontext format="html">
      <text><![CDATA[
      <div class="stack-comment">
      <h2>Drag and drop Parsons problems</h2>
      <p>STACK has advanced libraries for dealing with drag and drop problems.
      <ul>
      <li>The teacher can specify mutliple correct answers, e.g. here the two sub-proofs can occur in either order.</li>
      <li>The system automatically finds the closest proof to one correct proof, and gives feedback on how to change the student's answer to the closest correct proof.</li>
      </ul>
      Try getting the proof incorrect and look at the feedback generated.
      </p>
      </div>
      <p>Drag items from the available list on the right to the answer list on the left to construct a correct proof of the following theorem. </p>

<p><strong>Theorem.</strong> {@thm@}</p>
[[parsons input="ans1" log="true"]]
{# parsons_encode(proof_steps) #}
[[/parsons ]]
<p>[[input:ans1]] [[validation:ans1]]</p>]]></text>
    </questiontext>
    <generalfeedback format="html">
      <text><![CDATA[[[comment]]
This parsons' input will automatically feedback a model solution (the "teacher's answer") unless the input option 'hideanswer' is used or the PRT is on quiet respectively. 
Below are examples of how to format the worked solutions using the proof_display functions.
[[/comment]]

[[if test='len1=2' ]]
Notice this proof has sub-proofs, which can occur in any order.  Therefore, we have multiple correct versions of this proof. For example:
<table><tr>
<td><div class="proof">{@proof_display_para(tal[1], proof_steps)@}
<td><div class="proof">{@proof_display_para(tal[2], proof_steps)@}
</tr></table>
Can you see the differences between these proofs?
[[/if]]
[[if test='len1>2' ]]
{@proof_display_para(tal[1], proof_steps)@}
[[/if]]
[[if test='len1<2' ]]
{@proof_display_para(tal[1], proof_steps)@}
[[/if]]]]></text>
    </generalfeedback>
    <defaultgrade>1</defaultgrade>
    <penalty>0.1</penalty>
    <hidden>0</hidden>
    <idnumber></idnumber>
    <stackversion>
      <text>2025030700</text>
    </stackversion>
    <questionvariables>
      <text><![CDATA[stack_include_contrib("prooflib.mac");

/* STACK is distributed with a number of pre-written proofs.   See
   https://github.com/maths/moodle-qtype_stack/tree/master/stack/maxima/contrib/proofsamples
   The proof below is copied from   

   stack_include_contrib("proofsamples/odd-squaredodd.mac");

   We've copied it to make sure there are alternative proofs for iff.
*/

/****************************************************************/
thm:"\\(n\\) is odd if and only if \\(n^2\\) is odd.";

/****************************************************************/
proof_steps: [
    ["assodd",     "Assume that \\(n\\) is odd.",
                   "This is the hypothesis in the first half of an if any only if proof"],
    ["defn_odd",   "Then there exists an \\(m\\in\\mathbb{Z}\\) such that \\(n=2m+1\\)."],
    ["alg_odd",    "\\( n^2 = (2m+1)^2 = 2(2m^2+2m)+1.\\)"],
    ["def_M_odd",  "Define \\(M=2m^2+2m\\in\\mathbb{Z}\\) then \\(n^2=2M+1\\).",
                   "Notice we have satisfied the algebraic definition that \\(n^2\\) is an odd number."],
    ["conc_odd",   "Hence \\(n^2\\) is odd.",
                   "This is the conclusion in the first half of an if any only if proof"],

    ["contrapos",  "We reformulate \"\\(n^2\\) is odd \\(\\Rightarrow \\) \\(n\\) is odd \" as the contrapositive.",
                   "This reformulation enables us to start with \\(n\\) and not start with \\(n^2\\) which is simpler."],
    ["assnotodd",  "Assume that \\(n\\) is not odd.",
                   "This is the reformulated hypothesis in the second half of an if any only if proof"],
    ["even",       "Then \\(n\\) is even, and so there exists an \\(m\\in\\mathbb{Z}\\) such that \\(n=2m\\)."],
    ["alg_even",   "\\( n^2 = (2m)^2 = 2(2m^2).\\)"],
    ["def_M_even", "Define \\(M=2m^2\\in\\mathbb{Z}\\) then \\(n^2=2M\\)."],
    ["conc_even",  "Hence \\(n^2\\) is even.",
                   "This is the conclusion in the second half of an if any only if proof"
    ]
];

/****************************************************************/
/* This is how the teacher defines their answer, as nested proofs. */
proof1:proof("assodd","defn_odd","alg_odd","def_M_odd","conc_odd");
proof2:proof("contrapos","assnotodd","even","alg_even","def_M_even","conc_even");
proof_ans:proof_iff(proof1,proof2);

/* The variable "proof_steps", etc., are defined in the above file.  Permute the steps randomly. */ 
proof_steps: random_permutation(proof_steps);

/* Generate the alternative proofs. */
tal: proof_alternatives(proof_ans);
/* For teaching we're happy to find the closest correct proof, but for research we want to know which of the two a student is close to. */
taA:proof_flatten(first(tal));
taB:proof_flatten(second(tal));
len1: length(tal)
/* Below are wrong answers, the first generated by sorting the correct answer keys. */
wa1:apply(proof,sort(args(proof_flatten(tal[1]))));
wa2:proof("assodd","defn_odd","def_M_odd","conc_odd","contrapos","assnotodd","even","alg_even","def_M_even","conc_even");

/* Create a set of flattened proofs. */
tas: setify(map(proof_flatten, tal));]]></text>
    </questionvariables>
    <specificfeedback format="html">
      <text>[[feedback:prt1]]</text>
    </specificfeedback>
    <questionnote format="html">
      <text>{@ map(first, proof_steps) @}</text>
    </questionnote>
    <questiondescription format="html">
      <text><![CDATA[This question was adapted from the template for importing proofs from the STACK contrib directory.  See
https://github.com/maths/moodle-qtype_stack/tree/master/stack/maxima/contrib/proofsamples

It has been modified to show how to give partial credit in proofs.  In particular, this question is able to spot when only half of the "if and only if" proof is given.]]></text>
    </questiondescription>
    <questionsimplify>1</questionsimplify>
    <assumepositive>0</assumepositive>
    <assumereal>0</assumereal>
    <prtcorrect format="html">
      <text><![CDATA[<span style="font-size: 1.5em; color:green;"><i class="fa fa-check"></i></span> Correct answer, well done.]]></text>
    </prtcorrect>
    <prtpartiallycorrect format="html">
      <text><![CDATA[<span style="font-size: 1.5em; color:orange;"><i class="fa fa-adjust"></i></span> Your answer is partially correct.]]></text>
    </prtpartiallycorrect>
    <prtincorrect format="html">
      <text><![CDATA[<span style="font-size: 1.5em; color:red;"><i class="fa fa-times"></i></span> Incorrect answer.]]></text>
    </prtincorrect>
    <decimals>.</decimals>
    <scientificnotation>*10</scientificnotation>
    <multiplicationsign>dot</multiplicationsign>
    <sqrtsign>1</sqrtsign>
    <complexno>i</complexno>
    <inversetrig>cos-1</inversetrig>
    <logicsymbol>lang</logicsymbol>
    <matrixparens>[</matrixparens>
    <variantsselectionseed></variantsselectionseed>
    <input>
      <name>ans1</name>
      <type>parsons</type>
      <tans>[proof_ans, proof_steps]</tans>
      <boxsize>15</boxsize>
      <strictsyntax>1</strictsyntax>
      <insertstars>0</insertstars>
      <syntaxhint></syntaxhint>
      <syntaxattribute>0</syntaxattribute>
      <forbidwords></forbidwords>
      <allowwords></allowwords>
      <forbidfloat>1</forbidfloat>
      <requirelowestterms>0</requirelowestterms>
      <checkanswertype>0</checkanswertype>
      <mustverify>0</mustverify>
      <showvalidation>0</showvalidation>
      <options></options>
    </input>
    <prt>
      <name>prt1</name>
      <value>1.0000000</value>
      <autosimplify>1</autosimplify>
      <feedbackstyle>1</feedbackstyle>
      <feedbackvariables>
        <text>sa: parsons_decode(ans1);
[pd, saa]:proof_assessment(sa, proof_alternatives(proof_ans));

/* How close are they to proving just one part of the iff? */
[pd1, saa1]:proof_assessment(sa, proof_alternatives(proof1));
[pd2, saa2]:proof_assessment(sa, proof_alternatives(proof2));
</text>
      </feedbackvariables>
      <node>
        <name>0</name>
        <description>Run straight through</description>
        <answertest>AlgEquiv</answertest>
        <sans>sa</sans>
        <tans>taA</tans>
        <testoptions></testoptions>
        <quiet>1</quiet>
        <truescoremode>=</truescoremode>
        <truescore>1</truescore>
        <truepenalty></truepenalty>
        <truenextnode>-1</truenextnode>
        <trueanswernote>prt1-1-T</trueanswernote>
        <truefeedback format="html">
          <text></text>
        </truefeedback>
        <falsescoremode>=</falsescoremode>
        <falsescore>0</falsescore>
        <falsepenalty></falsepenalty>
        <falsenextnode>1</falsenextnode>
        <falseanswernote>prt1-1-F</falseanswernote>
        <falsefeedback format="html">
          <text></text>
        </falsefeedback>
      </node>
      <node>
        <name>1</name>
        <description><![CDATA["Only if" first block]]></description>
        <answertest>AlgEquiv</answertest>
        <sans>sa</sans>
        <tans>taB</tans>
        <testoptions></testoptions>
        <quiet>0</quiet>
        <truescoremode>=</truescoremode>
        <truescore>1</truescore>
        <truepenalty></truepenalty>
        <truenextnode>-1</truenextnode>
        <trueanswernote>prt1-2-T</trueanswernote>
        <truefeedback format="html">
          <text></text>
        </truefeedback>
        <falsescoremode>-</falsescoremode>
        <falsescore>0</falsescore>
        <falsepenalty></falsepenalty>
        <falsenextnode>2</falsenextnode>
        <falseanswernote>prt1-2-F</falseanswernote>
        <falsefeedback format="html">
          <text>{@proof_assessment_display(saa, proof_steps)@}</text>
        </falsefeedback>
      </node>
      <node>
        <name>2</name>
        <description>Condone a distance of 1 from a correct response</description>
        <answertest>GTE</answertest>
        <sans>1</sans>
        <tans>pd</tans>
        <testoptions></testoptions>
        <quiet>0</quiet>
        <truescoremode>=</truescoremode>
        <truescore>0.8</truescore>
        <truepenalty></truepenalty>
        <truenextnode>-1</truenextnode>
        <trueanswernote>prt1-3-T</trueanswernote>
        <truefeedback format="html">
          <text></text>
        </truefeedback>
        <falsescoremode>-</falsescoremode>
        <falsescore>0</falsescore>
        <falsepenalty></falsepenalty>
        <falsenextnode>3</falsenextnode>
        <falseanswernote>prt1-3-F</falseanswernote>
        <falsefeedback format="html">
          <text></text>
        </falsefeedback>
      </node>
      <node>
        <name>3</name>
        <description>Within 1 of first block only.</description>
        <answertest>GTE</answertest>
        <sans>1</sans>
        <tans>pd1</tans>
        <testoptions></testoptions>
        <quiet>0</quiet>
        <truescoremode>=</truescoremode>
        <truescore>0.4</truescore>
        <truepenalty></truepenalty>
        <truenextnode>-1</truenextnode>
        <trueanswernote>prt1-4-T</trueanswernote>
        <truefeedback format="html">
          <text><![CDATA[You appear to have only proved the "if" direction. This is an if and only if proof.  You need to prove both directions!]]></text>
        </truefeedback>
        <falsescoremode>-</falsescoremode>
        <falsescore>0</falsescore>
        <falsepenalty></falsepenalty>
        <falsenextnode>4</falsenextnode>
        <falseanswernote>prt1-4-F</falseanswernote>
        <falsefeedback format="html">
          <text></text>
        </falsefeedback>
      </node>
      <node>
        <name>4</name>
        <description>Within 1 of second block only.</description>
        <answertest>GTE</answertest>
        <sans>1</sans>
        <tans>pd2</tans>
        <testoptions></testoptions>
        <quiet>0</quiet>
        <truescoremode>=</truescoremode>
        <truescore>0.4</truescore>
        <truepenalty></truepenalty>
        <truenextnode>-1</truenextnode>
        <trueanswernote>prt1-5-T</trueanswernote>
        <truefeedback format="html">
          <text><![CDATA[You appear to have only proved the "only if" direction. This is an if and only if proof.  You need to prove both directions!]]></text>
        </truefeedback>
        <falsescoremode>-</falsescoremode>
        <falsescore>0</falsescore>
        <falsepenalty></falsepenalty>
        <falsenextnode>-1</falsenextnode>
        <falseanswernote>prt1-5-F</falseanswernote>
        <falsefeedback format="html">
          <text></text>
        </falsefeedback>
      </node>
    </prt>
    <deployedseed>263493547</deployedseed>
    <deployedseed>2080086703</deployedseed>
    <deployedseed>2119685624</deployedseed>
    <deployedseed>2065386162</deployedseed>
    <deployedseed>1272837801</deployedseed>
    <deployedseed>2105511895</deployedseed>
    <qtest>
      <testcase>1</testcase>
      <description>Test case assuming the teacher's input gets full marks.</description>
      <testinput>
        <name>ans1</name>
        <value>apply(parsons_answer,[tal[1], proof_steps])</value>
      </testinput>
      <expected>
        <name>prt1</name>
        <expectedscore>1.0000000</expectedscore>
        <expectedpenalty>0.0000000</expectedpenalty>
        <expectedanswernote>prt1-1-T</expectedanswernote>
      </expected>
    </qtest>
    <qtest>
      <testcase>2</testcase>
      <description><![CDATA[One incorret answer, based on "sorting" the correct answer keys.]]></description>
      <testinput>
        <name>ans1</name>
        <value>apply(parsons_answer,[wa1, proof_steps])</value>
      </testinput>
      <expected>
        <name>prt1</name>
        <expectedscore>0.0000000</expectedscore>
        <expectedpenalty>0.1000000</expectedpenalty>
        <expectedanswernote>prt1-5-F</expectedanswernote>
      </expected>
    </qtest>
    <qtest>
      <testcase>3</testcase>
      <description>If direction</description>
      <testinput>
        <name>ans1</name>
        <value>apply(parsons_answer,[proof1, proof_steps])</value>
      </testinput>
      <expected>
        <name>prt1</name>
        <expectedscore>0.4000000</expectedscore>
        <expectedpenalty>0.1000000</expectedpenalty>
        <expectedanswernote>prt1-4-T</expectedanswernote>
      </expected>
    </qtest>
    <qtest>
      <testcase>4</testcase>
      <description>Only if direction</description>
      <testinput>
        <name>ans1</name>
        <value>apply(parsons_answer,[proof2, proof_steps])</value>
      </testinput>
      <expected>
        <name>prt1</name>
        <expectedscore>0.4000000</expectedscore>
        <expectedpenalty>0.1000000</expectedpenalty>
        <expectedanswernote>prt1-5-T</expectedanswernote>
      </expected>
    </qtest>
    <qtest>
      <testcase>5</testcase>
      <description></description>
      <testinput>
        <name>ans1</name>
        <value>apply(parsons_answer,[taA, proof_steps])</value>
      </testinput>
      <expected>
        <name>prt1</name>
        <expectedscore>1.0000000</expectedscore>
        <expectedpenalty>0.0000000</expectedpenalty>
        <expectedanswernote>prt1-1-T</expectedanswernote>
      </expected>
    </qtest>
    <qtest>
      <testcase>6</testcase>
      <description></description>
      <testinput>
        <name>ans1</name>
        <value>apply(parsons_answer,[taB, proof_steps])</value>
      </testinput>
      <expected>
        <name>prt1</name>
        <expectedscore>1.0000000</expectedscore>
        <expectedpenalty>0.0000000</expectedpenalty>
        <expectedanswernote>prt1-2-T</expectedanswernote>
      </expected>
    </qtest>
    <qtest>
      <testcase>7</testcase>
      <description>Missing one step only - should get partial credit.</description>
      <testinput>
        <name>ans1</name>
        <value>apply(parsons_answer,[wa2, proof_steps])</value>
      </testinput>
      <expected>
        <name>prt1</name>
        <expectedscore>0.8000000</expectedscore>
        <expectedpenalty></expectedpenalty>
        <expectedanswernote>prt1-3-T</expectedanswernote>
      </expected>
    </qtest>
  </question>

</quiz>