// Numbas version: exam_results_page_options {"name": "Solve a linear programming problem", "extensions": ["jsxgraph", "optimisation"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false}, "question_groups": [{"pickingStrategy": "all-ordered", "questions": [{"parts": [{"showCorrectAnswer": true, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "prompt": "

Let $x$, $y$ be the number of units of {product_1s} and {product_2s} produced, respectively.

\n

What are the constraints on production resulting from the existing orders?

\n

$x \\geq$ [[0]]

\n

$y \\geq$ [[1]]

", "unitTests": [], "sortAnswers": false, "scripts": {}, "gaps": [{"correctAnswerFraction": false, "allowFractions": false, "customMarkingAlgorithm": "", "mustBeReduced": false, "extendBaseMarkingAlgorithm": true, "minValue": "xconstraint", "maxValue": "xconstraint", "unitTests": [], "correctAnswerStyle": "plain", "showFeedbackIcon": true, "scripts": {}, "notationStyles": ["plain", "en", "si-en"], "type": "numberentry", "variableReplacementStrategy": "originalfirst", "showCorrectAnswer": true, "variableReplacements": [], "marks": 1, "mustBeReducedPC": 0}, {"correctAnswerFraction": false, "allowFractions": false, "customMarkingAlgorithm": "", "mustBeReduced": false, "extendBaseMarkingAlgorithm": true, "minValue": "yconstraint", "maxValue": "yconstraint", "unitTests": [], "correctAnswerStyle": "plain", "showFeedbackIcon": true, "scripts": {}, "notationStyles": ["plain", "en", "si-en"], "type": "numberentry", "variableReplacementStrategy": "originalfirst", "showCorrectAnswer": true, "variableReplacements": [], "marks": 1, "mustBeReducedPC": 0}], "type": "gapfill", "variableReplacementStrategy": "originalfirst", "variableReplacements": [], "marks": 0, "showFeedbackIcon": true}, {"showCorrectAnswer": true, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "prompt": "

Now enter the constraints given by the availability of {resource_1} and {resource_2}:

\n

{capitalise(resource_1)}: [[0]] $x +$ [[1]] $y \\le$ [[2]]

\n

{capitalise(resource_2)}: [[3]] $x +$ [[4]] $y \\le$ [[5]]

Given the information on profits for {product_1s} and {product_2s}, write down the objective function which is to be maximised: [[0]]

", "unitTests": [], "sortAnswers": false, "scripts": {}, "gaps": [{"answer": "{profitx}*x+{profity}*y", "showCorrectAnswer": true, "extendBaseMarkingAlgorithm": true, "customMarkingAlgorithm": "", "checkingType": "absdiff", "vsetRangePoints": 5, "failureRate": 1, "checkVariableNames": false, "unitTests": [], "vsetRange": [0, 1], "type": "jme", "showFeedbackIcon": true, "scripts": {}, "answerSimplification": "all", "expectedVariableNames": [], "showPreview": true, "checkingAccuracy": 0.001, "variableReplacementStrategy": "originalfirst", "variableReplacements": [], "marks": 1}], "type": "gapfill", "variableReplacementStrategy": "originalfirst", "variableReplacements": [], "marks": 0, "showFeedbackIcon": true}, {"showCorrectAnswer": true, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "prompt": "

Input diagram goes here

\n

Drag the objective line on the diagram above to find the position which gives the maximum profit.

\n

Round your answers down to the nearest integer, end enter them below:

\n

Produce [[0]] {product_1s} and [[1]] {product_2s}, earning £ [[2]] in profit.

", "unitTests": [], "sortAnswers": false, "scripts": {}, "gaps": [{"correctAnswerFraction": false, "allowFractions": false, "customMarkingAlgorithm": "", "mustBeReduced": false, "extendBaseMarkingAlgorithm": true, "minValue": "best_x", "maxValue": "best_x", "unitTests": [], "correctAnswerStyle": "plain", "showFeedbackIcon": true, "scripts": {}, "notationStyles": ["plain", "en", "si-en"], "type": "numberentry", "variableReplacementStrategy": "alwaysreplace", "showCorrectAnswer": true, "variableReplacements": [{"part": "p0g0", "must_go_first": true, "variable": "xconstraint"}, {"part": "p0g1", "must_go_first": true, "variable": "yconstraint"}, {"part": "p1g0", "must_go_first": true, "variable": "resource1x"}, {"part": "p1g1", "must_go_first": true, "variable": "resource1y"}, {"part": "p1g2", "must_go_first": true, "variable": "totalresource1"}, {"part": "p1g3", "must_go_first": true, "variable": "resource2x"}, {"part": "p1g4", "must_go_first": true, "variable": "resource2y"}, {"part": "p1g5", "must_go_first": true, "variable": "totalresource2"}], "marks": 1, "mustBeReducedPC": 0}, {"correctAnswerFraction": false, "allowFractions": false, "customMarkingAlgorithm": "", "mustBeReduced": false, "extendBaseMarkingAlgorithm": true, "minValue": "best_y", "maxValue": "best_y", "unitTests": [], "correctAnswerStyle": "plain", "showFeedbackIcon": true, "scripts": {}, "notationStyles": ["plain", "en", "si-en"], "type": "numberentry", "variableReplacementStrategy": "alwaysreplace", "showCorrectAnswer": true, "variableReplacements": [{"part": "p0g0", "must_go_first": true, "variable": "xconstraint"}, {"part": "p0g1", "must_go_first": true, "variable": "yconstraint"}, {"part": "p1g0", "must_go_first": true, "variable": "resource1x"}, {"part": "p1g1", "must_go_first": true, "variable": "resource1y"}, {"part": "p1g2", "must_go_first": true, "variable": "totalresource1"}, {"part": "p1g3", "must_go_first": true, "variable": "resource2x"}, {"part": "p1g4", "must_go_first": true, "variable": "resource2y"}, {"part": "p1g5", "must_go_first": true, "variable": "totalresource2"}], "marks": 1, "mustBeReducedPC": 0}, {"correctAnswerFraction": false, "allowFractions": false, "customMarkingAlgorithm": "", "mustBeReduced": false, "extendBaseMarkingAlgorithm": true, "minValue": "best_profit", "maxValue": "best_profit", "unitTests": [], "correctAnswerStyle": "plain", "showFeedbackIcon": true, "scripts": {}, "notationStyles": ["plain", "en", "si-en"], "type": "numberentry", "variableReplacementStrategy": "originalfirst", "showCorrectAnswer": true, "variableReplacements": [{"part": "p3g0", "must_go_first": false, "variable": "best_x"}, {"part": "p3g1", "must_go_first": false, "variable": "best_y"}], "marks": 1, "mustBeReducedPC": 0}], "type": "gapfill", "variableReplacementStrategy": "originalfirst", "variableReplacements": [], "marks": 0, "showFeedbackIcon": true}], "variables": {"resource_1_units": {"templateType": "string", "group": "Text strings", "definition": "\"kg\"", "name": "resource_1_units", "description": "

Dimension of the first resource

"}, "resource1y": {"templateType": "anything", "group": "Constraints", "definition": "random(50..70)", "name": "resource1y", "description": "

How much of resource 1 the second product uses per unit

"}, "product_1": {"templateType": "string", "group": "Text strings", "definition": "\"bulletproof tea cosy\"", "name": "product_1", "description": "

Singular name of the first product

"}, "resource2x": {"templateType": "anything", "group": "Constraints", "definition": "\nrandom(250..450#10)", "name": "resource2x", "description": "

How much of resource 2 the first product uses per unit

"}, "business_long": {"templateType": "string", "group": "Text strings", "definition": "\"Amalgamated Mines and Sheep, Inc.\"", "name": "business_long", "description": "

The full name of the business

"}, "profits": {"templateType": "anything", "group": "Optimum strategy", "definition": "map(let(x,p[0],y,p[1],profitx*x+profity*y),p,intersection_points)", "name": "profits", "description": "

Profit earned at each intersection point

"}, "best_profit": {"templateType": "anything", "group": "Optimum strategy", "definition": "profit(best_x,best_y)", "name": "best_profit", "description": "

The profit at the best intersection point

"}, "product_2": {"templateType": "string", "group": "Text strings", "definition": "\"double-edged cardigan\"", "name": "product_2", "description": "

Singular name of the second product

"}, "constraint2xvalue": {"templateType": "anything", "group": "Bounds", "definition": "round(scalingfactor2*resource2y+xconstraint)", "name": "constraint2xvalue", "description": "

Where the constraint line for resource 2 cuts the y-constraint

"}, "r1": {"templateType": "anything", "group": "Constraints", "definition": "random(10..20)", "name": "r1", "description": "

The second constraint line cuts the x-constraint line at this value more than the y-constraint

"}, "constraint1yvalue": {"templateType": "anything", "group": "Bounds", "definition": "r2+constraint2yvalue", "name": "constraint1yvalue", "description": "

Where line given by resource 1 constraint cuts the x-constraint line.

\n

It is always greater than the point at which the second resource line cuts.

"}, "totalresource1": {"templateType": "anything", "group": "Constraints", "definition": "siground(\n scalingfactor1*resource1x*resource1y +\n resource1y*yconstraint +\n resource1x*xconstraint\n,3)", "name": "totalresource1", "description": "

Total amount of resource 1 available

"}, "business_short": {"templateType": "string", "group": "Text strings", "definition": "\"AMS\"", "name": "business_short", "description": "

A shorter name for the business, to be repeated throughout the text. If the business name is short enough for repeated use, leave this empty.

"}, "resource_2": {"templateType": "string", "group": "Text strings", "definition": "\"iron\"", "name": "resource_2", "description": "

The name of the second resource

"}, "best_x": {"templateType": "anything", "group": "Optimum strategy", "definition": "floor(best_x_float)", "name": "best_x", "description": "

The integer number of units of the first product to produce to earn the highest profit

"}, "intersection_points": {"templateType": "anything", "group": "Optimum strategy", "definition": "[\n [xconstraint, (totalresource1-resource1x*xconstraint)/resource1y], //resource 1 intersecting with minimum x\n [xconstraint, (totalresource2-resource2x*xconstraint)/resource2y], //resource 2 intersecting with minimum x\n [(totalresource1-resource1y*yconstraint)/resource1x, yconstraint], //resource 1 intersecting with minimum y\n [(totalresource2-resource2y*yconstraint)/resource2x, yconstraint], //resource 2 intersecting with minimum y\n let(y, (totalresource1-totalresource2*resource1x/resource2x)/(resource1y - resource1x/resource2x * resource2y),\n [(totalresource1-resource1y*y)/resource1x, y] // intersection of the two resource constraints\n )\n]", "name": "intersection_points", "description": "

Intersection points of the constraints - the optimum strategy will be one of these

Upper bound of the diagram

"}, "product_2s": {"templateType": "string", "group": "Text strings", "definition": "\"double-edged cardigans\"", "name": "product_2s", "description": "

Plural name of the second product

"}, "constraint1xvalue": {"templateType": "anything", "group": "Bounds", "definition": "round(scalingfactor1*resource1y+xconstraint)", "name": "constraint1xvalue", "description": "

Where the constraint line for resource 1 crosses the y-constraint

"}, "product_1s": {"templateType": "string", "group": "Text strings", "definition": "\"bulletproof tea cosies\"", "name": "product_1s", "description": "

Plural name of the first product

"}, "xconstraint": {"templateType": "anything", "group": "Constraints", "definition": "\nrandom(4..10)", "name": "xconstraint", "description": "

Minimum production of the first product

"}, "profitx": {"templateType": "anything", "group": "Profit", "definition": "//the coeff of x in the objective function\nrandom(2..4)", "name": "profitx", "description": "

Profit for each unit of the first product sold

"}, "best_y_float": {"templateType": "anything", "group": "Optimum strategy", "definition": "intersection_points[best_point][1]", "name": "best_y_float", "description": "

The number of units of the second product to produce to earn the highest profit, if fractions are allowed

"}, "possible_points": {"templateType": "anything", "group": "Optimum strategy", "definition": "filter(\n let(x,floor(intersection_points[j][0]),y,floor(intersection_points[j][1]),\n resource1x*x+resource1y*y <= totalresource1+1 and \n resource2x*x+resource2y*y <= totalresource2+1 and\n x>=xconstraint and\n y>=yconstraint\n ),\n j,\n 0..len(intersection_points)-1\n)", "name": "possible_points", "description": "

Indices of intersection points which satisfy all the constraints.

"}, "line_names": {"templateType": "list of strings", "group": "Optimum strategy", "definition": "[ \"the amount of resource 1 used\", \"the amount of resource 2 used\", \"the minimum amount of X produced\", \"the maximum amount of Y produced\" ]", "name": "line_names", "description": "

Names of the lines, coded as in the definition of best_lines

"}, "resource1x": {"templateType": "anything", "group": "Constraints", "definition": "random(20..40)", "name": "resource1x", "description": "

How much of resource 1 the first product uses per unit

"}, "yconstraint": {"templateType": "anything", "group": "Constraints", "definition": "random(4..10)", "name": "yconstraint", "description": "

Minimum production of the second product

"}, "best_y": {"templateType": "anything", "group": "Optimum strategy", "definition": "floor(best_y_float)", "name": "best_y", "description": "

The integer number of units of the second product to produce to earn the highest profit

"}, "resource_1": {"templateType": "string", "group": "Text strings", "definition": "\"wool\"", "name": "resource_1", "description": "

The name of the first resource

"}, "resource2y": {"templateType": "anything", "group": "Constraints", "definition": "\nrandom(1500..3000#100)", "name": "resource2y", "description": "

How much of resource 2 the second product uses per unit

"}, "totalresource2": {"templateType": "anything", "group": "Constraints", "definition": "siground(\n scalingfactor2*resource2x*resource2y +\n resource2y*yconstraint +\n resource2x*xconstraint\n,3)", "name": "totalresource2", "description": "

Total amount of resource 2 available

"}, "scalingfactor1": {"templateType": "anything", "group": "Constraints", "definition": "precround((r1+r2)/resource1x,1)", "name": "scalingfactor1", "description": ""}, "best_x_float": {"templateType": "anything", "group": "Optimum strategy", "definition": "intersection_points[best_point][0]", "name": "best_x_float", "description": "

The number of units of X to produce to earn the highest profit, if fractions are allowed

"}, "best_profit_float": {"templateType": "anything", "group": "Optimum strategy", "definition": "profit(best_x_float,best_y_float)", "name": "best_profit_float", "description": "

The profit at the best intersection point, if fractions of units are allowed

"}, "profity": {"templateType": "anything", "group": "Profit", "definition": "//the coeff of y in the objective function\nceil(profitx*(resource1y/resource1x)*random(1.5..3))", "name": "profity", "description": "

Profit for each unit of the second product sold

"}, "scalingfactor2": {"templateType": "anything", "group": "Constraints", "definition": "precround((r1)/resource2x,2)", "name": "scalingfactor2", "description": ""}, "r2": {"templateType": "anything", "group": "Constraints", "definition": "random(5..15)", "name": "r2", "description": "

The first constraint line cuts the x-constraint line at this value greater than where the second constraint cuts.

"}, "best_point": {"templateType": "anything", "group": "Optimum strategy", "definition": "best_by(possible_points,profits)", "name": "best_point", "description": "

The index of the valid intersection point with the highest profit

"}, "boundx": {"templateType": "anything", "group": "Bounds", "definition": "max(constraint1xvalue,constraint2xvalue)", "name": "boundx", "description": "

Right bound of the diagram

"}, "best_lines": {"templateType": "anything", "group": "Optimum strategy", "definition": "[[0,2],[1,2],[0,3],[1,3],[0,1]][best_point]", "name": "best_lines", "description": "

Which lines are involed in the best point? Coded as follows:

\n

0 - resource 1

\n

1 - resource 2

\n

2 - minimum x

\n

3 - minimum y

\n

Note that (minimum x,minimum y) is never the best point

"}, "constraint2yvalue": {"templateType": "anything", "group": "Bounds", "definition": "r1+yconstraint", "name": "constraint2yvalue", "description": "

Where the constraint line for the second resource cuts the x-constraint.

\n

Second resource line cuts x-constraint at a point greater than the y-constraint

"}, "resource_2_units": {"templateType": "string", "group": "Text strings", "definition": "\"tonnes\"", "name": "resource_2_units", "description": "

Dimension of the second resource

"}}, "ungrouped_variables": [], "name": "Solve a linear programming problem", "variable_groups": [{"variables": ["xconstraint", "yconstraint", "resource1x", "resource1y", "resource2x", "resource2y", "r1", "r2", "scalingfactor1", "scalingfactor2", "totalresource1", "totalresource2"], "name": "Constraints"}, {"variables": ["boundx", "boundy", "constraint1xvalue", "constraint1yvalue", "constraint2xvalue", "constraint2yvalue"], "name": "Bounds"}, {"variables": ["profitx", "profity"], "name": "Profit"}, {"variables": ["intersection_points", "possible_points", "profits", "best_point", "best_x_float", "best_y_float", "best_profit_float", "best_x", "best_y", "best_profit", "best_lines", "line_names"], "name": "Optimum strategy"}, {"variables": ["business_long", "business_short", "business", "resource_1", "resource_1_units", "resource_2", "resource_2_units", "product_1", "product_1s", "product_2", "product_2s"], "name": "Text strings"}], "functions": {"profit": {"type": "number", "language": "jme", "definition": "profitx*x+profity*y", "parameters": [["x", "number"], ["y", "number"]]}, "best_by": {"type": "number", "language": "javascript", "definition": "// l1 is a list of indices on l2\n// return the element of l1 which has the biggest corresponding value in l2 \n// (i.e. i such that l2[l1[i]] is biggest)\n\nvar best_1 = null;\nvar best_2 = null;\nfor(var i=0;ibest_2) {\n best_2 = l2[l1[i]];\n best_1 = l1[i];\n }\n}\nreturn best_1", "parameters": [["l1", "list"], ["l2", "list"]]}}, "variablesTest": {"condition": "", "maxRuns": 100}, "statement": "

\n

Existing orders require {business} to make at least {xconstraint} {product_1s} and {yconstraint} {product_2s} each day.

\n

Each unit of {product_1s} produced uses {resource1x} {resource_1_units} {resource_1} and {resource2x} {resource_2_units} {resource_2}.

\n

Each unit of {product_2s} produced uses {resource1y} {resource_1_units} {resource_1} and {resource2y} {resource_2_units} {resource_2}.

\n

However, the resources are limited: {business} can only obtain {totalresource1} {resource_1_units} {resource_1} and {totalresource2} {resource_2_units} {resource_2} each day.

\n

Each sale of a unit of {product_1s} gives £{profitx} profit. Each sale of a unit of {product_2s} gives £{profity} profit.

", "tags": ["constraints", "linear programming", "objective function", "template"], "rulesets": {}, "preamble": {"css": "", "js": "function userinput_diagram() {\n\nwith(question.unwrappedVariables) {\n\n var options = {\n x_bound: boundx, \n y_bound: boundy\n };\n\n options.objective_line_coordinates = [[0,0],[1,-profitx/profity]];\n \n function getStudentAnswer(path) {\n var part = question.getPart(path);\n return ko.computed(function() {\n return parseFloat(part.display.studentAnswer());\n });\n }\n \n options.minimum_x = getStudentAnswer('p0g0');\n options.minimum_y = getStudentAnswer('p0g1');\n\n var x_coefficient_1 = getStudentAnswer('p1g0');\n var y_coefficient_1 = getStudentAnswer('p1g1');\n var total_1 = getStudentAnswer('p1g2');\n options.inequality_1_coordinates = [ko.computed(function() {\n return [-total_1(),x_coefficient_1(),y_coefficient_1()];\n })];\n\n options.inequality_1_ok = ko.computed(function() {\n return !(isNaN(x_coefficient_1()) || isNaN(y_coefficient_1()) || isNaN(total_1()));\n });\n\n var x_coefficient_2 = getStudentAnswer('p1g3');\n var y_coefficient_2 = getStudentAnswer('p1g4');\n var total_2 = getStudentAnswer('p1g5');\n options.inequality_2_coordinates = [ko.computed(function() {\n return [-total_2(),x_coefficient_2(),y_coefficient_2()];\n })];\n\n options.inequality_2_ok = ko.computed(function() {\n return !(isNaN(x_coefficient_2()) || isNaN(y_coefficient_2()) || isNaN(total_2()));\n });\n\n var result = Numbas.extensions.optimisation.linear_programming_board(options);\n question.display.html.find('.lp-graph').html('').append(result.div);\n}\n}\n\nfunction advice_diagram() {\nwith(question.unwrappedVariables) {\n\n var result = Numbas.extensions.optimisation.linear_programming_board({\n x_bound: boundx,\n y_bound: boundy,\n objective_line_coordinates: [[0,best_profit_float/profity],[1,(best_profit_float-profitx)/profity]],\n minimum_x: xconstraint,\n minimum_y: yconstraint,\n inequality_1_coordinates: [-totalresource1, resource1x, resource1y],\n inequality_2_coordinates: [-totalresource2, resource2x, resource2y]\n });\n question.display.html.find('#advicediagram').html('').append(result.div);\n}\n}\n\n('body').on('question-html-attached',function() {\n userinput_diagram();\n advice_diagram();\n});\n"}, "type": "question", "metadata": {"licence": "Creative Commons Attribution 4.0 International", "description": " Student is given a set of constraints for a linear program. Asked to enter the constraints as inequalities, and then to identify the optimal solution. \n Problem with solving the simultaneous equations gven by the constraints - too unwieldy and not given enough marks for doing so. Best if the point of intersection is given graphically by putting the mouse over the intersection. "}, "extensions": ["jsxgraph", "optimisation"], "advice": " #### a) \n The existing orders give two constraints: \n \\begin{align} x &\\geq \\var{xconstraint} \\\\ y &\\geq \\var{yconstraint} \\end{align} \n #### b) \n The limits on the two resources, and the amounts of each resource used to produce a unit of each product, give two further constraints: \n \\begin{align} \\simplify{{resource1x}x + {resource1y}y} &\\leq \\var{totalresource1} \\\\ \\simplify{{resource2x}x + {resource2y}y} &\\leq \\var{totalresource2} \\end{align} \n #### c) \n The objective function to be maximised is the total profit earned, that is, the sum of the profits earned from each unit made: \n \$\\simplify{{profitx}x + {profity}y} \$ \n #### d) \n The solution graph goes here \n It is clear that the minimum profit is given by producing enough {product_1s} and {product_2s} so that the existing demand is met and no more. You can see this by moving the objective function line down to the intersection of the two minimum constraint lines - there are no other points inside the feasible region under the objective line. \n Next, drag the objective function line upwards until there are no points above the objective line in the feasible region. At this point, the objective line touches the intersection of the lines representing the constraints for {line_names[best_lines[0]]} and {line_names[best_lines[1]]}. \n You can find the coordinates of this point by solving the equations for these two lines: \n \$\\simplify{{resource1x}x + {resource1y}y = {totalresource1}} \$\$\\simplify{{resource2x}x + {resource2y}y = {totalresource2}} \$ \n \$\\simplify{{resource2x}x + {resource2y}y = {totalresource2}} \$\$x = \\var{xconstraint} \$\$y = \\var{yconstraint} \$ \n The solution to this system of equations isx = \\var{best_x}$,$y = \\var{best_y}\$, giving a profit of

\n

\$\\text{Profit} = \\simplify[]{{profitx}*{best_x} + {profity}*{best_y}} = \\text{£}\\var{best_profit} \$

", "contributors": [{"name": "Bill Foster", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/6/"}, {"name": "Chris Graham", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/369/"}, {"name": "Newcastle University Mathematics and Statistics", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/697/"}]}]}], "contributors": [{"name": "Bill Foster", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/6/"}, {"name": "Chris Graham", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/369/"}, {"name": "Newcastle University Mathematics and Statistics", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/697/"}]}