// Numbas version: finer_feedback_settings {"name": "JSXGraph: interactive 2D optimisation", "extensions": ["jsxgraph"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "question_groups": [{"pickingStrategy": "all-ordered", "questions": [{"name": "JSXGraph: interactive 2D optimisation", "tags": [], "metadata": {"description": "

A 2D linear programming problem: optimise the profit from producing two different kinds of product, which both use the same limited resources.

\n

A JSXGraph diagram illustrates the problem and can be used to find an answer.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "

A factory produces two items, {prod_1_name} and {prod_2_name}.

\n

They both use {resource_1_name} and {resource_2_name}.

\n

You have {max_resource_1} {resource_1_unit} {resource_1_name} and {max_resource_2} {resource_2_unit} {resource_2_name}.

\n

Each {prod_1_name} uses {resource_1_per_prod_1} {resource_1_unit} {resource_1_name} and {resource_2_per_prod_1} {resource_2_unit} {resource_2_name}, and can be sold for {currency(prod_1_price,\"£\",\"p\")}.

\n

Each {prod_2_name} uses {resource_1_per_prod_2} {resource_1_unit} {resource_1_name} and {resource_2_per_prod_2} {resource_2_unit} {resource_2_name}, and can be sold for {currency(prod_2_price,\"£\",\"p\")}.

\n

The graph below shows these constraints: the horizontal axis corresponds to the number of {prod_1_name} produced, and the vertical axis corresponds to the number of {prod_2_name} produced.

\n

The solid lines show the constraints corresponding to the amounts of {resource_1_name} and {resource_2_name} available, and the dashed line represents revenue.

\n

{diagram}

", "advice": "", "rulesets": {}, "extensions": ["jsxgraph"], "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true}, "constants": [], "variables": {"max_resource_1": {"name": "max_resource_1", "group": "Setup", "definition": "random(100..200#10)", "description": "", "templateType": "anything", "can_override": false}, "resource_1_per_prod_1": {"name": "resource_1_per_prod_1", "group": "Setup", "definition": "round(max_resource_1/random(1..10))", "description": "", "templateType": "anything", "can_override": false}, "resource_1_per_prod_2": {"name": "resource_1_per_prod_2", "group": "Setup", "definition": "round(max_resource_1/random(8..20))", "description": "", "templateType": "anything", "can_override": false}, "max_resource_2": {"name": "max_resource_2", "group": "Setup", "definition": "random(1000..2000#50)", "description": "", "templateType": "anything", "can_override": false}, "resource_2_per_prod_1": {"name": "resource_2_per_prod_1", "group": "Setup", "definition": "round(max_resource_2/random(8..20))", "description": "", "templateType": "anything", "can_override": false}, "resource_2_per_prod_2": {"name": "resource_2_per_prod_2", "group": "Setup", "definition": "round(max_resource_2/random(1..10))", "description": "", "templateType": "anything", "can_override": false}, "resource_1_name, resource_2_name": {"name": "resource_1_name, resource_2_name", "group": "Ungrouped variables", "definition": "[\"metal\", \"plastic\"]", "description": "", "templateType": "anything", "can_override": false}, "prod_1_name, prod_2_name": {"name": "prod_1_name, prod_2_name", "group": "Ungrouped variables", "definition": "[\"toy\", \"kitchen utensil\"]", "description": "", "templateType": "anything", "can_override": false}, "prod_1_price": {"name": "prod_1_price", "group": "Setup", "definition": "random(1..3#0.1)", "description": "", "templateType": "anything", "can_override": false}, "prod_2_price": {"name": "prod_2_price", "group": "Setup", "definition": "random(1..3#0.1)", "description": "", "templateType": "anything", "can_override": false}, "resource_1_unit, resource_2_unit": {"name": "resource_1_unit, resource_2_unit", "group": "Ungrouped variables", "definition": "[\"kg\", \"kg\"]", "description": "", "templateType": "anything", "can_override": false}, "diagram": {"name": "diagram", "group": "Diagram", "definition": "jessiecode(400,400,[-prod_1_max_production*0.3, prod_2_max_production*1.5, prod_1_max_production*1.5, -prod_2_max_production*0.3],\"\"\"\n l1a = point(0,{max_resource_1/resource_1_per_prod_2}) <>;\n l1b = point({max_resource_1/resource_1_per_prod_1},0) <>;\n l1 = line(l1a,l1b) <>;\n\n l2a = point(0,{max_resource_2/resource_2_per_prod_2}) <>;\n l2b = point({max_resource_2/resource_2_per_prod_1},0) <>;\n l2 = line(l2a,l2b) <>;\n \n oa = point(0,0) <>;\n ob = point(function() {\"\"\"+\"\"\" return oa.X()+1; },function() {\"\"\"+\"\"\" return oa.Y() - {prod_1_price/prod_2_price}; }) <>;\n objective = line(oa,ob) <>;\n\"\"\")", "description": "", "templateType": "anything", "can_override": false}, "prod_1_max_production": {"name": "prod_1_max_production", "group": "Setup", "definition": "min(max_resource_1/resource_1_per_prod_1, max_resource_2/resource_2_per_prod_1)", "description": "", "templateType": "anything", "can_override": false}, "prod_2_max_production": {"name": "prod_2_max_production", "group": "Setup", "definition": "min(max_resource_1/resource_1_per_prod_2, max_resource_2/resource_2_per_prod_2)", "description": "", "templateType": "anything", "can_override": false}, "points_to_consider": {"name": "points_to_consider", "group": "Marking", "definition": "[\n [floor(prod_1_max_production),0],\n [0,floor(prod_2_max_production)]\n] + let([ix,iy],intersection,\n [[floor(ix),floor(iy)], [floor(ix),ceil(iy)], [ceil(ix),floor(iy)]]\n)", "description": "", "templateType": "anything", "can_override": false}, "intersection": {"name": "intersection", "group": "Marking", "definition": "let(\n m, matrix([resource_1_per_prod_1, resource_1_per_prod_2], [resource_2_per_prod_1, resource_2_per_prod_2]),\n d, det(m),\n im, 1/d * matrix([resource_2_per_prod_2, -resource_1_per_prod_2], [-resource_2_per_prod_1, resource_1_per_prod_1]),\n im*vector(max_resource_1, max_resource_2)\n)", "description": "", "templateType": "anything", "can_override": false}, "valid_points": {"name": "valid_points", "group": "Marking", "definition": "filter(\n let([prod_1,prod_2],p,\n resource_1_per_prod_1 * prod_1 + resource_1_per_prod_2 * prod_2 <= max_resource_1\n and\n resource_2_per_prod_1 * prod_1 + resource_2_per_prod_2 * prod_2 <= max_resource_2\n ),\n p,\n points_to_consider\n)\n ", "description": "", "templateType": "anything", "can_override": false}, "revenue": {"name": "revenue", "group": "Marking", "definition": "map(\n prod_1_price * prod_1 + prod_2_price * prod_2,\n [prod_1,prod_2],\n valid_points\n)", "description": "", "templateType": "anything", "can_override": false}, "best_x,best_y": {"name": "best_x,best_y", "group": "Ungrouped variables", "definition": "let(\n i, filter(revenue[i]=top_revenue, i, 0..len(revenue)-1)[0],\n valid_points[i]\n)", "description": "", "templateType": "anything", "can_override": false}, "top_revenue": {"name": "top_revenue", "group": "Marking", "definition": "max(revenue)", "description": "", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["resource_1_name, resource_2_name", "prod_1_name, prod_2_name", "resource_1_unit, resource_2_unit", "best_x,best_y"], "variable_groups": [{"name": "Setup", "variables": ["max_resource_1", "resource_1_per_prod_1", "resource_1_per_prod_2", "resource_2_per_prod_1", "resource_2_per_prod_2", "max_resource_2", "prod_1_price", "prod_2_price", "prod_1_max_production", "prod_2_max_production"]}, {"name": "Diagram", "variables": ["diagram"]}, {"name": "Marking", "variables": ["points_to_consider", "intersection", "valid_points", "revenue", "top_revenue"]}], "functions": {}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "gapfill", "useCustomName": false, "customName": "", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "student_prod_1: interpreted_answers[0]\n\nstudent_prod_2: interpreted_answers[1]\n\nstudent_revenue:\n student_prod_1 * prod_1_price + student_prod_2 * prod_2_price\n\nmark:\n correctif(student_revenue >= top_revenue)", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

How many of each product should you make, in order to maximise your income? You can type your answer in the boxes below, or move the point on the diagram above.

\n

[[0]] {prod_1_name}

\n

[[1]] {prod_2_name}

\n

", "gaps": [{"type": "numberentry", "useCustomName": true, "customName": "Number of {prod_1_name} to make", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "point: diagram[\"p\"]\n\npos: jxg_position(point)\n\njxg_input:\n if(pos[1]=studentNumber, [], [jxg_set_position(point, vector(studentNumber,pos[1]))])\n\njxg_output:\n dpformat(pos[0],0)", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": false, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "best_x", "maxValue": "best_x", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "precisionType": "dp", "precision": 0, "precisionPartialCredit": 0, "precisionMessage": "You have not given your answer to the correct precision.", "strictPrecision": false, "showPrecisionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": true, "customName": "Number of {prod_2_name} to make", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "point: diagram[\"p\"]\n\npos: jxg_position(point)\n\njxg_input:\n if(pos[1]=studentNumber, [], [jxg_set_position(point, vector(pos[0],studentNumber))])\n\njxg_output:\n dpformat(pos[1],0)", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": false, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "best_y", "maxValue": "best_y", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "precisionType": "dp", "precision": 0, "precisionPartialCredit": 0, "precisionMessage": "You have not given your answer to the correct precision.", "strictPrecision": false, "showPrecisionHint": false, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "sortAnswers": false}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always", "type": "question", "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "http://localhost:8000/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}]}]}], "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "http://localhost:8000/accounts/profile/1/"}, {"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}]}