// Numbas version: exam_results_page_options {"name": "Student can choose names of constants of integration in a 2nd order ODE solution - check every permutation of the constants", "extensions": [], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "question_groups": [{"pickingStrategy": "all-ordered", "questions": [{"name": "Student can choose names of constants of integration in a 2nd order ODE solution - check every permutation of the constants", "tags": [], "metadata": {"description": "

A custom marking algorithm picks out the names of the constants of integration that the student has used in their answer, and tries mapping them to every permutation of the constants used in the expected answer. The version that agrees the most with the expected answer is used for testing equivalence.

\n

If the student uses fewer constants of integration, it still works (but they must be wrong), and if they use too many, it's still marked correct if the other variables have no impact on the result. For example, adding $+0t$ to an expression which otherwise doesn't use $t$ would have no impact.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "", "advice": "", "rulesets": {}, "extensions": [], "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": [], "variable_groups": [], "functions": {}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "jme", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "free_constants (Free variables in the student's answer that aren't x):\n set(findvars(studentExpr)) - set(\"x\")\n\nexpected_constants:\n set(findvars(correctExpr)) - set(\"x\")\n\naaaaa:\n apply(vset);\n apply(free_constants);\n map(\n let(\n d, dict(map([f, name(ex)], [ex,f], zip(expected_constants, permuted_constants))),\n studentCompare, substitute(d, studentCompare),\n studentCompare\n ),\n permuted_constants,\n permutations(free_constants, length(free_constants))\n )\n\n\npermutation_fails:\n apply(vset);\n apply(free_constants);\n map(\n let(\n d, dict(map([f, name(ex)], [ex,f], zip(expected_constants, permuted_constants))),\n studentCompare, substitute(d, studentCompare),\n agree,\n map(\n try(\n scope_case_sensitive(resultsequal(unset(question_definitions,eval(studentCompare,vars)),unset(question_definitions,eval(correctCompare,vars)),settings[\"checkingType\"],settings[\"checkingAccuracy\"]),settings[\"caseSensitive\"]),\n message,\n warn(translate(\"part.jme.answer invalid\",[\"message\":message]));\n fail(translate(\"part.jme.answer invalid\",[\"message\":message]));\n false\n ),\n vars,\n vset\n ),\n numFails, len(filter(not x,x,agree)),\n numFails\n ),\n permuted_constants,\n permutations(free_constants, length(free_constants))\n )\n\nnumFails: min(permutation_fails)", "extendBaseMarkingAlgorithm": true, "unitTests": [{"variables": [], "name": "a*e^2*cos(x) + b*sin(x)*e^2", "answer": {"valid": true, "value": "a*e^2*cos(x)+b*sin(x)*e^2"}, "notes": [{"name": "mark", "expected": {"value": "nothing", "messages": ["Your answer is numerically correct.\n\nYou were awarded 1 mark."], "warnings": [], "error": "", "valid": true, "credit": 1}}, {"name": "studentexpr", "expected": {"value": "A*e^2*cos(x) + B*sin(x)*e^2", "messages": [], "warnings": [], "error": "", "valid": true, "credit": 0}}]}, {"variables": [], "name": "a*sin(x)*e^2 + b*cos(x)*e^2", "answer": {"valid": true, "value": "a*sin(x)*e^2 + b*cos(x)*e^2"}, "notes": [{"name": "mark", "expected": {"value": "nothing", "messages": ["Your answer is numerically correct.\n\nYou were awarded 1 mark."], "warnings": [], "error": "", "valid": true, "credit": 1}}, {"name": "studentexpr", "expected": {"value": "B*sin(x)*e^2 + A*cos(x)*e^2", "messages": [], "warnings": [], "error": "", "valid": true, "credit": 0}}]}, {"variables": [], "name": "a*cos(x)*e^2 + b*sin(x)*e^2", "answer": {"valid": true, "value": "a*cos(x)*e^2 + a*sin(x)*e^2"}, "notes": [{"name": "mark", "expected": {"value": "nothing", "messages": ["Your answer is incorrect."], "warnings": [], "error": "", "valid": true, "credit": 0}}, {"name": "studentexpr", "expected": {"value": "B*cos(x)*e^2 + B*sin(x)*e^2", "messages": [], "warnings": [], "error": "", "valid": true, "credit": 0}}]}], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

The answer is $Ax^2 + Bx + C$

", "answer": "A*x^2 + B*x + C", "showPreview": true, "checkingType": "absdiff", "checkingAccuracy": 0.001, "failureRate": 1, "vsetRangePoints": 5, "vsetRange": [0, 1], "checkVariableNames": false, "singleLetterVariables": true, "allowUnknownFunctions": true, "implicitFunctionComposition": false, "caseSensitive": false, "valuegenerators": [{"name": "a", "value": ""}, {"name": "b", "value": ""}, {"name": "c", "value": ""}, {"name": "x", "value": ""}]}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always", "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}]}]}], "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}]}