// Numbas version: exam_results_page_options {"name": "Denis's copy of mathcentre: Linear Programming (Business)", "question_groups": [{"pickingStrategy": "all-ordered", "name": "", "questions": [{"name": "Linear Programming 6", "extensions": ["jsxgraph"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Bill Foster", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/6/"}], "functions": {"diagram": {"definition": "var solpt;\nvar solx;\nvar soly;\nvar Pfunction=function(x,y){return xprofit*x+yprofit*y;};\nvar pt;\nvar xboundR=(resource*1000-Yresource*(yconstraint))/Xresource+5;\nvar xboundT=(timeavailable*60-Ytime*(yconstraint))/Xtime+5;\nvar yboundR=(resource*1000-Xresource*(xconstraint))/Yresource+5;\nvar yboundT=(timeavailable*60-Xtime*(xconstraint))/Ytime+5;\nvar xbound=Math.max(xboundR,xboundT,yboundR,yboundT);\nvar ybound=xbound;\nvar div = Numbas.extensions.jsxgraph.makeBoard('400px','400px',{\n boundingBox:[-20,ybound,xbound,-20],\n axis:true,\n showNavigation:false,\n grid:false\n});\nvar board=div.board;\n\n//Create lines using homogeneous coordinates - beware,ax+by+c=0\n//is entered as [c,a,b]\nvar lineR=board.create('line',[-resource*1000,Xresource,Yresource],{name:'Cocoa',withLabel:true,fixed:true});\nvar lineT=board.create('line',[-60*timeavailable,Xtime,Ytime],{name:'Time',withLabel:true,fixed:true});\nvar ep=board.create('intersection',[lineR,lineT],{name:'T',withLabel:true,face:'x',fixed:true});\n\nvar xconst=board.create('line',[[xconstraint,0],[xconstraint,ybound]],{strokeColor:'red',fixed:true});\nvar yconst=board.create('line',[[0,yconstraint],[xbound,yconstraint]],{strokeColor:'red',fixed:true});\n\nvar al=board.create('point',[xconstraint,yconstraint],{name:'',face:'x',fixed:true});\nvar be;\nvar ga;\nvar te=((resource*1000-Yresource*yconstraint)/Xresource>(timeavailable*60-Ytime*yconstraint)/Xtime);\nvar te1=((resource*1000-Xresource*xconstraint)/Yresource>(timeavailable*60-Xtime*xconstraint)/Ytime);\nif(!te)\n {be=board.create('point',[(resource*1000-Yresource*yconstraint)/Xresource,yconstraint],{name:'Q',face:'x',fixed:true});}\nelse \n {be=board.create('point',[(timeavailable*60-Ytime*yconstraint)/Xtime,yconstraint],{name:'Q',face:'x',fixed:true});}\nif(!te1)\n{ga=board.create('point',[xconstraint,(resource*1000-Xresource*xconstraint)/Yresource],{name:'R',face:'x',fixed:true});}\nelse\n {ga=board.create('point',[xconstraint,(timeavailable*60-Xtime*xconstraint)/Ytime],{name:'R',face:'x',fixed:true});}\n\nif((!te&& te1)||(te&&!te1)){\n board.create('polygon',[al,be,ep,ga],{name:\"Feasible Region\",withLabel:false});\n if(Pfunction(ep.X(),ep.Y())>Math.max(Pfunction(ga.X(),ga.Y()),Pfunction(be.X(),be.Y())))\n{solx=ep.X();soly=ep.Y();pt='T';}\n else {\n if(Pfunction(be.X(),be.Y())>Pfunction(ga.X(),ga.Y()))\n {solx=be.X();soly=be.Y();pt='Q';}\n \n else \n {solx=ga.X();soly=ga.Y();pt='R';}\n }\n}\n \n else{\n board.create('polygon',[al,be,ga],{name:\"Feasible Region\",withLabel:false});\n \n if(Pfunction(be.X(),be.Y())>Pfunction(ga.X(),ga.Y()))\n{solx=be.X();soly=be.Y();pt='Q';}\n else \n{solx=ga.X();soly=ga.Y();pt='R';}\n }\n \n\nvar solx=Numbas.math.precround(Numbas.math.niceNumber(solx),1);\nvar soly=Numbas.math.precround(Numbas.math.niceNumber(soly),1);\nvar P=board.create('slider',[[xbound-50, ybound-10], [xbound-50,ybound-60], [0, Pfunction(solx,soly)/100, 100]],{name:'Profit'});\nvar PL=board.create('line',[[function(){return 100*P.Value()/(xprofit);},0],[0,function(){return 100*P.Value()/(yprofit);}]],{strokeColor:'green',dash:1,name:'Profit',withLabel:true});\nvar t1 = board.create('text',[xbound-300,ybound-200,\"solutions:x= \"+solx+\",y= \"+soly]);\nvar html = $(question.display.html);\nhtml.find('#xsol').text(solx);\nhtml.find('#ysol').text(soly);\nhtml.find('#ptname').text(pt);\nreturn div;\n", "type": "html", "language": "javascript", "parameters": [["Xresource", "number"], ["Yresource", "number"], ["Xtime", "number"], ["Ytime", "number"], ["xconstraint", "number"], ["yconstraint", "number"], ["resource", "number"], ["timeavailable", "number"], ["xprofit", "number"], ["yprofit", "number"]]}, "userinput": {"definition": "var xboundR=(resource*1000-Yresource*(yconstraint))/Xresource+5;\nvar xboundT=(timeavailable*60-Ytime*(yconstraint))/Xtime+5;\nvar yboundR=(resource*1000-Xresource*(xconstraint))/Yresource+5;\nvar yboundT=(timeavailable*60-Xtime*(xconstraint))/Ytime+5;\nvar xbound=Math.max(xboundR,xboundT,yboundR,yboundT);\nvar ybound=xbound;\nvar profitondemand=(xconstraint*xprofit+yconstraint*yprofit)/100\nvar div = Numbas.extensions.jsxgraph.makeBoard('400px','400px',{\n boundingBox:[-20,ybound,xbound,-20],\n axis:true,\n showNavigation:false,\n grid:false\n});\nvar board=div.board;\nvar P=board.create('slider',[[xbound-50, ybound-10], [xbound-50,ybound-60], [0, profitondemand, 100]],{name:'Profit'});\nvar PL=board.create('line',[[function(){return 100*P.Value()/(xprofit);},0],[0,function(){return 100*P.Value()/(yprofit);}]],{strokeColor:'green',dash:1,name:'Profit',withLabel:true});\nquestion.signals.on('HTMLAttached',function(e) {\n \n //set up KO observables to compute the coordinates from the student's input\n var xcon = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[0].display.studentAnswer());\n });\n var ycon = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[1].display.studentAnswer());\n });\n var aa = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[2].display.studentAnswer());\n });\n var ba = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[3].display.studentAnswer());\n });\n var ca = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[4].display.studentAnswer());\n });\n var ta_coordinates = ko.computed(function() {\nif(isNaN(aa()) || isNaN(ba()) || isNaN(ca())) {\n // return [0,0,1];\n}\nreturn [-ca(),aa(),ba()];\n });\n \n // create the lines\n var x_constraint_line = board.create('line',[[xcon,0],[xcon,1]],{strokeColor:'red',fixed:true, straightFirst: false});\n var y_constraint_line = board.create('line',[[0,ycon],[1,ycon]],{strokeColor:'red',fixed:true, straightFirst: false});;\nvar inequality_linea = board.create('line',[ta_coordinates],{name:'Cocoa',withLabel:true});\n var ab = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[5].display.studentAnswer());\n });\n var bb = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[6].display.studentAnswer());\n });\n var cb = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[7].display.studentAnswer());\n });\n var tb_coordinates = ko.computed(function() {\nif(isNaN(ab()) || isNaN(bb()) || isNaN(cb())) {\n // return [0,0,1];\n}\nreturn [-cb(),ab(),bb()];\n });\n \n var inequality_lineb = board.create('line',[tb_coordinates],{name:'Time',withLabel:true});\n var ep=board.create('intersection',[inequality_linea,inequality_lineb],{name:'T',face:'x',visible:false});\n var al=board.create('point',[xcon,ycon],{name:'P',face:'x',fixed:true});\n var be1=board.create('intersection',[inequality_linea,y_constraint_line],{name:'Q',face:'x',fixed:true,visible:false});\n var be2=board.create('intersection',[inequality_lineb,y_constraint_line],{name:'Q',face:'x',fixed:true,visible:false});\n var ga=board.create('intersection',[x_constraint_line,inequality_linea],{name:'R',face:'x',fixed:true,visible:false});\n var del=board.create('intersection',[x_constraint_line,inequality_lineb],{name:'R',face:'x',fixed:true,visible:false});\n var fr1=board.create('polygon',[al,be2,ep,ga],{name:\"Feasible Region\",visible:false}); \n var fr2=board.create('polygon',[al,be1,ga],{name:\"Feasible Region\",visible:false}); \n var fr3=board.create('polygon',[al,be2,del],{name:\"Feasible Region\",visible:false}); \n var fr4=board.create('polygon',[al,be1,ep,del],{name:\"Feasible Region\",visible:false}); \n ko.computed(function(){ \n// look at the observables, so this function gets called whenever they change\nxcon(),ycon(),ta_coordinates(),tb_coordinates();\n\nvar lineAOK=!(isNaN(aa()) || isNaN(ba()) || isNaN(ca()));\nvar lineBOK=!(isNaN(ab()) || isNaN(bb()) || isNaN(cb()));\nvar consxOK= !isNaN(xcon());var consyOK= !isNaN(ycon());\n// show/hide the lines based on whether the student input is valid\nvar te=(be1.X()> be2.X());\nvar te1=(ga.Y()> del.Y());\nx_constraint_line.setAttribute({'visible':consxOK});\ny_constraint_line.setAttribute({'visible': consyOK}); \ninequality_linea.setAttribute({'visible': lineAOK});\ninequality_lineb.setAttribute({'visible': lineBOK});\nal.setAttribute({'visible':consxOK&&consyOK});\nep.setAttribute({'visible':((lineAOK&&lineBOK))&&((!te&&te1)||(te&&!te1))});\nbe1.setAttribute({'visible':lineAOK&&!te});\nbe2.setAttribute({'visible':lineBOK&&(te)});\nga.setAttribute({'visible':(lineAOK&&consxOK)&&!te1});\ndel.setAttribute({'visible':(lineBOK&&consxOK)&&(te1)}); \nvar fr1_visible = ((consxOK&&consyOK)&&(lineAOK&&lineBOK))&&((te)&&!te1);\nvar fr2_visible = consxOK&&consyOK&&lineAOK&&lineBOK&&!te&&!te1;\nvar fr3_visible = consxOK&&consyOK&&lineAOK&&lineBOK&&(te)&&(te1);\nvar fr4_visible = (consxOK&&consyOK)&&(lineAOK&&lineBOK)&&(!te)&&(te1);\nfr1.setAttribute({'visible':fr1_visible, 'fillOpacity': fr1_visible ? 0.3 : 0});\nfr2.setAttribute({'visible':fr2_visible, 'fillOpacity': fr2_visible ? 0.3 : 0}); \nfr3.setAttribute({'visible':fr3_visible, 'fillOpacity': fr3_visible ? 0.3 : 0}); \nfr4.setAttribute({'visible':fr4_visible, 'fillOpacity': fr4_visible ? 0.3 : 0}); \n// prompt JSXGraph to reevaluate the coordinate functions\nboard.update(); \n }); \n});\n\nreturn div;\n", "type": "html", "language": "javascript", "parameters": [["Xresource", "number"], ["Yresource", "number"], ["Xtime", "number"], ["Ytime", "number"], ["xconstraint", "number"], ["yconstraint", "number"], ["resource", "number"], ["timeavailable", "number"], ["xprofit", "number"], ["yprofit", "number"]]}}, "tags": ["Feasible region", "Jsxgraph", "constraints", "graphical method", "jsxgraph", "linear programming", "maximise", "objective function"], "type": "question", "advice": "
{diagram(xresource,yresource,xtime,ytime,xconstraint,yconstraint,resource,timeavailable,xprofit,yprofit)}
\nIt is clear that the minimum profit is given by producing enough toys so that demand is met and no more. You can see this by moving the slider so that the objective function line goes through the point giving the demand. Note that this is given in the diagram in the statement of the question.
\nSolving the pair of equations given by the lines which intersect at point we find that a solution for maximum profit is:
\nNumber of Bears to be produced, $x=\\;$ (to one decimal place).
\nNumber of Cats to be produced, $y=\\;$ (to one decimal place).
\nIf these are not whole numbers, then you will have to adjust them accordingly to get realistic solutions.
\n", "rulesets": {}, "parts": [{"showcorrectanswer": true, "prompt": "Let $x,\\;y$ be the number of units of Asteroids, Blackholes produced respectively.
\n{userinput(xresource,yresource,xtime,ytime,xconstraint,yconstraint,resource,timeavailable,xprofit,yprofit)}
\nWhat are the constraints on production.?
\n$x \\ge\\;$[[0]] $y \\ge\\;$[[1]]
\nNow input the constraints given by availability of cocoa and time:
\nCocoa: [[2]]$x\\;+\\;$[[3]]$y\\;\\le\\;$[[4]] (in grammes)
\nTime: [[5]]$x\\;+\\;$[[6]]$y\\;\\le\\;$[[7]] (in minutes)
\nInput the objective function which maximises profit.
\nObjective function :[[8]]
\nThe profit objective function is displayed above as a green dashed line. It is initially set at the profit if demand is just met.
\nOnce you have input all of the constraints you can use the slider to move the objective function to the value of $x$ and $y$ in the Feasible region to maximise profit.
\nUsing this diagram find values of the production of $x$ and $y$ which satisfy the constraints and maximise the profit in a day's production by identifying the equations you need to solve algebraically.
\n", "gaps": [{"showcorrectanswer": true, "minvalue": "xconstraint", "type": "numberentry", "maxvalue": "xconstraint", "marks": 1.0, "showPrecisionHint": false}, {"showcorrectanswer": true, "minvalue": "yconstraint", "type": "numberentry", "maxvalue": "yconstraint", "marks": 1.0, "showPrecisionHint": false}, {"showcorrectanswer": true, "minvalue": "xresource", "type": "numberentry", "maxvalue": "xresource", "marks": 1.0, "showPrecisionHint": false}, {"showcorrectanswer": true, "minvalue": "yresource", "type": "numberentry", "maxvalue": "yresource", "marks": 1.0, "showPrecisionHint": false}, {"showcorrectanswer": true, "minvalue": "resource*1000", "type": "numberentry", "maxvalue": "resource*1000", "marks": 1.0, "showPrecisionHint": false}, {"showcorrectanswer": true, "minvalue": "xtime", "type": "numberentry", "maxvalue": "xtime", "marks": 1.0, "showPrecisionHint": false}, {"showcorrectanswer": true, "minvalue": "ytime", "type": "numberentry", "maxvalue": "ytime", "marks": 1.0, "showPrecisionHint": false}, {"showcorrectanswer": true, "minvalue": "timeavailable*60", "type": "numberentry", "maxvalue": "timeavailable*60", "marks": 1.0, "showPrecisionHint": false}, {"expectedvariablenames": [], "checkingaccuracy": 0.001, "vsetrange": [0.0, 1.0], "showpreview": true, "vsetrangepoints": 5.0, "showcorrectanswer": true, "answersimplification": "all", "marks": 1.0, "answer": "{xprofit}*x+{yprofit}*y", "checkingtype": "absdiff", "checkvariablenames": false, "type": "jme"}], "type": "gapfill", "marks": 0.0}], "statement": "A chocolate manufacturer produces two types of chocolate bar: Asteroids and Blackholes.
\nProduction of an Asteroid bar uses {xresource}g of cocoa and {xtime} minute(s) of machine time, whereas a Blackhole bar requires {yresource}g of cocoa and {ytime} minute(s) of machine time.
\nAltogether, {resource}kg of cocoa are available each day.
\nThe company employs a single machine operator who works on the production of these bars for {timeavailable} hours per day.
\nThe manufacturer must make at least {xconstraint} Asteroid and {yconstraint} Blackholes each day to keep up with demand.
\nThe manufacturer makes {xprofit}p profit from each Asteroid bar and {yprofit}p profit from each Blackhole bar.
\n(a) Formulate the chocolate manufacturer’s situation as a linear programming problem and input this information in the fields below.
\n(b) After this input a suitable diagram will be drawn on screen to enable the problem to be solved graphically, but will give approximate solutions.
\n(c) Use your diagram to find an approximate value for the company’s minimum and maximum profit, £P.
\n(d) Using the information given by the diagram, once you have completed all inputs, you can identify and solve the pair of equations in order to find the production that achieves maximum profit. This give a more accurate solution, but you may meed to adjust to obtain whole numbers of products!
", "variable_groups": [], "progress": "in-progress", "preamble": {"css": "", "js": ""}, "variables": {"timeavailable": {"definition": "max(ceil((xtime*xconstraint+ytime*yconstraint +60)/60),random(7..9))\n", "name": "timeavailable"}, "yconstraint": {"definition": "random(30..50#5)\n", "name": "yconstraint"}, "resource": {"definition": "ceil((xresource*xconstraint+yresource*yconstraint+random(500..1000))/1000)", "name": "resource"}, "xprofit": {"definition": "random(8..18)", "name": "xprofit"}, "yprofit": {"definition": "random(10..25 except xprofit)", "name": "yprofit"}, "xconstraint": {"definition": "random(30..60#5)", "name": "xconstraint"}, "ytime": {"definition": "random(1..3#0.5 except xtime)", "name": "ytime"}, "yresource": {"definition": "if(xtime > ytime, xresource+random(1,1.5,2),xresource-random(1,1.5,2))", "name": "yresource"}, "xtime": {"definition": "random(1..3#0.5)", "name": "xtime"}, "xresource": {"definition": "random(5..10#0.5)", "name": "xresource"}}, "metadata": {"notes": "30/01/2014:
\nFirst version finished. Algebraic solution of equations to be added.
\nDisplay needs improving. Repositioning of text to be done.
", "description": "Linear program to find maximum profit using an objective function from the manufacture of two items with constraints on time and materials.
\nThis assumes that there are constraints on the number of items produced i.e. there is a mininum number of each.
", "licence": "Creative Commons Attribution 4.0 International"}, "showQuestionGroupNames": false, "question_groups": [{"name": "", "pickingStrategy": "all-ordered", "pickQuestions": 0, "questions": []}]}, {"name": "Stephanie's copy of Generic LP 2", "extensions": ["stats", "jsxgraph"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Stephanie Greaves", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/340/"}], "functions": {}, "ungrouped_variables": ["yconstraint", "constraint1xvalue", "r1", "boundx", "boundy", "constraint2yvalue", "scalingfactor1", "scalingfactor2", "resource1y", "resource1x", "xconstraint", "constraint2xvalue", "resource2x", "resource2y", "profity", "profitx", "r2", "constraint1yvalue", "totalresource1", "totalresource2"], "tags": ["LP", "constraints", "generic", "linear programming", "objective function", "programming", "template"], "preamble": {"css": "", "js": "\n// declare variables to be shared between the functions userinput_board and diagram\nvar xconstraint;\nvar yconstraint;\nvar coeff1x;\nvar coeff1y;\nvar coeff2x;\nvar coeff2y;\nvar resource1;\nvar resource2;\nvar boundx;\nvar boundy;\nvar profitx;\nvar profity;\n\n\n// get_variables is called after the randomised variables have been generated\nfunction get_variables() {\n var scope = question.scope;\n coeff1x = Numbas.jme.unwrapValue(scope.variables.resource1x);\n coeff1y = Numbas.jme.unwrapValue(scope.variables.resource1y);\n coeff2x= Numbas.jme.unwrapValue(scope.variables.resource2x);\n coeff2y = Numbas.jme.unwrapValue(scope.variables.resource2y);\n resource1 = Numbas.jme.unwrapValue(scope.variables.totalresource1);\n resource2= Numbas.jme.unwrapValue(scope.variables.totalresource2);\n xconstraint = Numbas.jme.unwrapValue(scope.variables.xconstraint);\n yconstraint = Numbas.jme.unwrapValue(scope.variables.yconstraint);\n boundx = Numbas.jme.unwrapValue(scope.variables.boundx);\n boundy = Numbas.jme.unwrapValue(scope.variables.boundy);\n profitx = Numbas.jme.unwrapValue(scope.variables.profitx);\n profity = Numbas.jme.unwrapValue(scope.variables.profity);\n profitondemand=(xconstraint*profitx+yconstraint*profity);\n constraint1xvalue=Numbas.jme.unwrapValue(scope.variables.constraint1xvalue);\n constraint2xvalue=Numbas.jme.unwrapValue(scope.variables.constraint2xvalue);\n constraint1yvalue=Numbas.jme.unwrapValue(scope.variables.constraint1yvalue);\n constraint2yvalue=Numbas.jme.unwrapValue(scope.variables.constraint2yvalue);\n}\n\n// all the variables declared above can be accessed by any other function\nfunction userinput_board(){\n var div = Numbas.extensions.jsxgraph.makeBoard('400px','400px',{\nboundingBox:[-2,boundy+2,boundx+2,-2],\naxis:true,\nshowNavigation:false,\ngrid:true\n });\n \n $(question.display.html).find('#userinput').html('').append(div);\n var board=div.board;\n var P=board.create('slider',[[boundx-12, boundy-5], [boundx-12,boundy-15], [0, profitondemand, 1000]],{name:'Profit'});\n var PL=board.create('line',[[function(){return P.Value()/(profitx);},0],[0,function(){return P.Value()/(profity);}]],{strokeColor:'green',dash:1,name:'Profit',withLabel:true});\n var xcon = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[0].display.studentAnswer());\n });\n var ycon = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[1].display.studentAnswer());\n });\n var aa = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[2].display.studentAnswer());\n });\n var ba = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[3].display.studentAnswer());\n });\n var ca = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[4].display.studentAnswer());\n });\n var ta_coordinates = ko.computed(function() {\nif(isNaN(aa()) || isNaN(ba()) || isNaN(ca())) {\n // return [0,0,1];\n}\nreturn [-ca(),aa(),ba()];\n });\n \n // create the lines\n var x_constraint_line = board.create('line',[[xcon,0],[xcon,1]],{strokeColor:'red',fixed:true, straightFirst: false});\n var y_constraint_line = board.create('line',[[0,ycon],[1,ycon]],{strokeColor:'red',fixed:true, straightFirst: false});;\n var inequality_linea = board.create('line',[ta_coordinates],{name:'Resource 1',withLabel:true});\n var ab = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[5].display.studentAnswer());\n });\n var bb = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[6].display.studentAnswer());\n });\n var cb = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[7].display.studentAnswer());\n });\n var tb_coordinates = ko.computed(function() {\nif(isNaN(ab()) || isNaN(bb()) || isNaN(cb())) {\n // return [0,0,1];\n}\nreturn [-cb(),ab(),bb()];\n });\n \n var inequality_lineb = board.create('line',[tb_coordinates],{name:'Resource 2',withLabel:true});\n var ep=board.create('intersection',[inequality_linea,inequality_lineb],{name:'I',face:'x',visible:false});\n var al=board.create('point',[xcon,ycon],{name:'P',face:'x',fixed:true});\n var be1=board.create('intersection',[inequality_linea,y_constraint_line],{name:'Q',face:'x',fixed:true,visible:false});\n var be2=board.create('intersection',[inequality_lineb,y_constraint_line],{name:'Q',face:'x',fixed:true,visible:false});\n var ga=board.create('intersection',[x_constraint_line,inequality_linea],{name:'R',face:'x',fixed:true,visible:false});\n var del=board.create('intersection',[x_constraint_line,inequality_lineb],{name:'R',face:'x',fixed:true,visible:false});\n var fr1=board.create('polygon',[al,be2,ep,ga],{name:\"Feasible Region\",visible:false}); \n var fr2=board.create('polygon',[al,be1,ga],{name:\"Feasible Region\",visible:false}); \n var fr3=board.create('polygon',[al,be2,del],{name:\"Feasible Region\",visible:false}); \n var fr4=board.create('polygon',[al,be1,ep,del],{name:\"Feasible Region\",visible:false}); \n ko.computed(function(){ \n// look at the observables, so this function gets called whenever they change\nxcon(),ycon(),ta_coordinates(),tb_coordinates();\n\nvar lineAOK=!(isNaN(aa()) || isNaN(ba()) || isNaN(ca()));\nvar lineBOK=!(isNaN(ab()) || isNaN(bb()) || isNaN(cb()));\nvar consxOK= !isNaN(xcon());var consyOK= !isNaN(ycon());\n// show/hide the lines based on whether the student input is valid\nvar te=(be1.X()> be2.X());\nvar te1=(ga.Y()> del.Y());\nx_constraint_line.setAttribute({'visible':consxOK});\ny_constraint_line.setAttribute({'visible': consyOK}); \ninequality_linea.setAttribute({'visible': lineAOK});\ninequality_lineb.setAttribute({'visible': lineBOK});\nal.setAttribute({'visible':consxOK&&consyOK});\nep.setAttribute({'visible':((lineAOK&&lineBOK))&&((!te&&te1)||(te&&!te1))});\nbe1.setAttribute({'visible':lineAOK&&!te});\nbe2.setAttribute({'visible':lineBOK&&(te)});\nga.setAttribute({'visible':(lineAOK&&consxOK)&&!te1});\ndel.setAttribute({'visible':(lineBOK&&consxOK)&&(te1)}); \nvar fr1_visible = ((consxOK&&consyOK)&&(lineAOK&&lineBOK))&&((te)&&!te1);\nvar fr2_visible = consxOK&&consyOK&&lineAOK&&lineBOK&&!te&&!te1;\nvar fr3_visible = consxOK&&consyOK&&lineAOK&&lineBOK&&(te)&&(te1);\nvar fr4_visible = (consxOK&&consyOK)&&(lineAOK&&lineBOK)&&(!te)&&(te1);\nfr1.setAttribute({'visible':fr1_visible, 'fillOpacity': fr1_visible ? 0.3 : 0});\nfr2.setAttribute({'visible':fr2_visible, 'fillOpacity': fr2_visible ? 0.3 : 0}); \nfr3.setAttribute({'visible':fr3_visible, 'fillOpacity': fr3_visible ? 0.3 : 0}); \nfr4.setAttribute({'visible':fr4_visible, 'fillOpacity': fr4_visible ? 0.3 : 0}); \n// prompt JSXGraph to reevaluate the coordinate functions\nboard.update(); \n }); \n}\nfunction diagram(){\n var solx;\n var soly;\n var Pfunction=function(x,y){return profitx*x+profity*y;};\n var pt;\n var div = Numbas.extensions.jsxgraph.makeBoard('400px','400px',{\nboundingBox:[-2,boundy+2,boundx+2,-4],\naxis:true,\nshowNavigation:false,\ngrid:true\n });\n var board=div.board;\n $(question.display.html).find('#advicediagram').append(div);\n //Create lines using homogeneous coordinates - beware,ax+by+c=0\n //is entered as [c,a,b]\n var liner1=board.create('line',[-resource1,coeff1x,coeff1y],{name:'Resource 1',withLabel:true,fixed:true});\n var liner2=board.create('line',[-resource2,coeff2x,coeff2y],{name:'Resource 2',withLabel:true,fixed:true});\n var ep=board.create('intersection',[liner1,liner2],{name:'I',withLabel:true,face:'x',fixed:true});\n \n var xconst=board.create('line',[[xconstraint,0],[xconstraint,boundy]],{strokeColor:'red',fixed:true});\n var yconst=board.create('line',[[0,yconstraint],[boundx,yconstraint]],{strokeColor:'red',fixed:true});\n var pt1intx=board.create('intersection',[liner1,xconst],{face:'x',fixed:true,name:' '});\n var pt1inty=board.create('intersection',[liner1,yconst],{face:'x',fixed:true,name:' '});\n var pt2intx=board.create('intersection',[liner2,xconst],{face:'x',fixed:true,name:' '});\n var pt2inty=board.create('intersection',[liner2,yconst],{face:'x',fixed:true,name:' '});\n var al=board.create('point',[xconstraint,yconstraint],{name:'P',face:'x',fixed:true});\n var be;\n var ga;\n var te=(pt1inty.X()>pt2inty.X());\n var te1=(pt1intx.Y()>pt2intx.Y());\n if(!te)\n {be=board.create('point',[pt1inty.X(),yconstraint],{name:'Q',face:'x',fixed:true});}\n else \n {be=board.create('point',[pt2inty.X(),yconstraint],{name:'Q',face:'x',fixed:true});}\n if(!te1)\n {ga=board.create('point',[xconstraint,pt1intx.Y()],{name:'R',face:'x',fixed:true});}\n else\n {ga=board.create('point',[xconstraint,pt2intx.Y()],{name:'R',face:'x',fixed:true});}\n \n if((!te&& te1)||(te&&!te1)){\nboard.create('polygon',[al,be,ep,ga],{name:\"Feasible Region\",withLabel:false});\nif(Pfunction(ep.X(),ep.Y())>Math.max(Pfunction(ga.X(),ga.Y()),Pfunction(be.X(),be.Y())))\n {solx=ep.X();soly=ep.Y();pt='I';}\nelse {\n if(Pfunction(be.X(),be.Y())>Pfunction(ga.X(),ga.Y()))\n{solx=be.X();soly=be.Y();pt='Q';}\n \n else \n {solx=ga.X();soly=ga.Y();pt='R';}\n}\n }\n \n else{\nboard.create('polygon',[al,be,ga],{name:\"Feasible Region\",withLabel:false});\n\nif(Pfunction(be.X(),be.Y())>Pfunction(ga.X(),ga.Y()))\n {solx=be.X();soly=be.Y();pt='Q';}\nelse \n{solx=ga.X();soly=ga.Y();pt='R';}\n }\n \n \n var solx=Numbas.math.precround(Numbas.math.niceNumber(solx),1);\n var soly=Numbas.math.precround(Numbas.math.niceNumber(soly),1);\n var P=board.create('slider',[[boundx-10, boundy-5], [boundx-10,boundy-15], [0, Pfunction(solx,soly), 1000]],{name:'Profit'});\n var PL=board.create('line',[[function(){return P.Value()/(profitx);},0],[0,function(){return P.Value()/(profity);}]],{strokeColor:'green',dash:1,name:'Profit',withLabel:true});\n var t1 = board.create('text',[1,-2,\"solutions:x= \"+solx+\",y= \"+soly]);\n var html = $(question.display.html);\n html.find('#xsol').text(solx);\n html.find('#ysol').text(soly);\n html.find('#ptname').text(pt);\n}\n\nquestion.signals.on('HTMLAttached',function() {\n //assign values to the common variables\n get_variables();\n //diagram user draws on in the question.\n userinput_board();\n //solution diagram found in Advice.\n diagram();\n});\n"}, "advice": "The solution
\n\nIt is clear that the minimum profit is given by producing enough snapjacks and snaxz so that demand is met and no more. You can see this by moving the slider so that the objective function line goes through the point giving the demand. Note that this is given in the diagram in the statement of the question.
\nSolving the pair of equations given by the lines which intersect at point we find that a solution for maximum profit is:
\nNumber of snapjacks to be produced, $x=\\;$ (to one decimal place).
\nNumber of snaxz to be produced, $y=\\;$ (to one decimal place).
\nIf these are not whole numbers, then you will have to adjust them accordingly to get realistic solutions.
\n", "rulesets": {}, "parts": [{"prompt": "Input diagram
\nLet $x,\\;y$ be the number of units of snapjacks and snaxz produced respectively.
\nWhat are the constraints on production ?
\n$x \\ge\\;$[[0]] $y \\ge\\;$[[1]]
\nNow input the constraints given by availability of porridge oats and cocoa:
\nPorridge oats: [[2]]$x\\;+\\;$[[3]]$y\\;\\le\\;$[[4]]
\ncocoa: [[5]]$x\\;+\\;$[[6]]$y\\;\\le\\;$[[7]]
\nGiven the information on profits for snapjacks and snaxz input the objective function which is to be maximised: [[8]]
\nHence by moving the slider find an approximate value for the maximum profit and also solve the two equations which intersect at the maximum profit point and so find the amounts of snapjacks and snaxz to be produced to achieve this maximum profit.
", "marks": 0, "gaps": [{"allowFractions": false, "marks": 1, "maxValue": "xconstraint", "minValue": "xconstraint", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "yconstraint", "minValue": "yconstraint", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "resource1x", "minValue": "resource1x", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "resource1y", "minValue": "resource1y", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "totalresource1", "minValue": "totalresource1", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "resource2x", "minValue": "resource2x", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "resource2y", "minValue": "resource2y", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "totalresource2", "minValue": "totalresource2", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"vsetrangepoints": 5, "expectedvariablenames": [], "checkingaccuracy": 0.001, "vsetrange": [0, 1], "showpreview": true, "marks": 1, "showCorrectAnswer": true, "answersimplification": "all", "scripts": {}, "answer": "{profitx}*x+{profity}*y", "checkingtype": "absdiff", "checkvariablenames": false, "type": "jme"}], "showCorrectAnswer": true, "scripts": {}, "type": "gapfill"}], "statement": "snapjacks and snaxz are two popular products.
\nThere must be at least {xconstraint} batches of snapjacks and {yconstraint} batches of snaxz produced each day to meet ordered sales.
\nEach snapjack batch needs {resource1x}g porridge oats and {resource2x}g cocoa every day.
\nEach snaxz batch needs {resource1y}g porridge oats and {resource2y}g cocoa every day.
\nHowever, the resources are limited:
\n{totalresource1}g of porridge oats each day.
\n{totalresource2}g of cocoa each day.
\nEach sale of a unit of snapjacks gives £{profitx} profit. Each sale of a unit of snaxz gives £{profity} profit.
\n", "variable_groups": [], "variablesTest": {"maxRuns": 100, "condition": ""}, "variables": {"yconstraint": {"definition": "//least allocation of Y - forced.\nrandom(4..10)", "templateType": "anything", "group": "Ungrouped variables", "name": "yconstraint", "description": ""}, "constraint1xvalue": {"definition": "round(scalingfactor1*resource1y+xconstraint)", "templateType": "anything", "group": "Ungrouped variables", "name": "constraint1xvalue", "description": ""}, "r1": {"definition": "//the second constraint line cuts the xconstraint line at this value more than the yconstraint\nrandom(10..20)", "templateType": "anything", "group": "Ungrouped variables", "name": "r1", "description": ""}, "boundx": {"definition": "max(constraint1xvalue,constraint2xvalue)", "templateType": "anything", "group": "Ungrouped variables", "name": "boundx", "description": ""}, "boundy": {"definition": "max(constraint1yvalue,constraint2yvalue)", "templateType": "anything", "group": "Ungrouped variables", "name": "boundy", "description": ""}, "constraint2yvalue": {"definition": "//second resource line cuts x=xconstraint at a point greater than the yconstraint\nr1+yconstraint", "templateType": "anything", "group": "Ungrouped variables", "name": "constraint2yvalue", "description": ""}, "scalingfactor1": {"definition": "precround((r1+r2)/resource1x,1)", "templateType": "anything", "group": "Ungrouped variables", "name": "scalingfactor1", "description": ""}, "scalingfactor2": {"definition": "precround((r1)/resource2x,2)", "templateType": "anything", "group": "Ungrouped variables", "name": "scalingfactor2", "description": ""}, "resource1y": {"definition": "//How much of resource 1 Y uses per unit\nrandom(50..70)", "templateType": "anything", "group": "Ungrouped variables", "name": "resource1y", "description": ""}, "resource1x": {"definition": "//How much of resource 1 X uses per unit\nrandom(20..40)", "templateType": "anything", "group": "Ungrouped variables", "name": "resource1x", "description": ""}, "xconstraint": {"definition": "//least allocation of X - forced\nrandom(4..10)", "templateType": "anything", "group": "Ungrouped variables", "name": "xconstraint", "description": ""}, "constraint2xvalue": {"definition": "round(scalingfactor2*resource2y+xconstraint)", "templateType": "anything", "group": "Ungrouped variables", "name": "constraint2xvalue", "description": ""}, "resource2x": {"definition": "////How much of resource 2 X uses per unit\nrandom(250..450#10)", "templateType": "anything", "group": "Ungrouped variables", "name": "resource2x", "description": ""}, "resource2y": {"definition": "//How much of resource 2 Y uses per unit\nrandom(1500..3000#100)", "templateType": "anything", "group": "Ungrouped variables", "name": "resource2y", "description": ""}, "profity": {"definition": "//the coeff of y in the objective function\nceil(profitx*(resource1y/resource1x)*random(1.5..3))", "templateType": "anything", "group": "Ungrouped variables", "name": "profity", "description": ""}, "profitx": {"definition": "//the coeff of x in the objective function\nrandom(2..4)", "templateType": "anything", "group": "Ungrouped variables", "name": "profitx", "description": ""}, "r2": {"definition": "//the first constraint line cuts the xconstraint line at this value \n//greater than where the second constraint cuts.\nrandom(5..15)", "templateType": "anything", "group": "Ungrouped variables", "name": "r2", "description": ""}, "constraint1yvalue": {"definition": "//Where line given by resource 1 constraint cuts the x=xconstraint line. \n//It is always greater than the point at which the second resource line cuts.\nr2+constraint2yvalue", "templateType": "anything", "group": "Ungrouped variables", "name": "constraint1yvalue", "description": ""}, "totalresource1": {"definition": "siground(scalingfactor1*resource1x*resource1y+resource1y*yconstraint+resource1x*xconstraint,3)", "templateType": "anything", "group": "Ungrouped variables", "name": "totalresource1", "description": ""}, "totalresource2": {"definition": "siground(scalingfactor2*resource2x*resource2y+resource2y*yconstraint+resource2x*xconstraint,3)", "templateType": "anything", "group": "Ungrouped variables", "name": "totalresource2", "description": ""}}, "metadata": {"notes": "The following variables can be changed by the author to fit their own examples:
\nxconstraint, yconstraint, resource1x, resource1y,resource2x,resource2y, profitx,profity,r1,r2. All other variables are calculated from these.
\nSee individual variables in the variables list for an explanation of these.
\nYou can also change the names; X, Y, Resource 1, Resource 2, profit......
", "description": "Template type question.
\nAuthors can change values of some of the variables (see Author's Notes). Also change names to suit the example.
\n", "licence": "None specified"}, "type": "question", "showQuestionGroupNames": false, "question_groups": [{"name": "", "pickingStrategy": "all-ordered", "pickQuestions": 0, "questions": []}]}, {"name": "Stephanie's copy of Linear Programming 4", "extensions": ["jsxgraph"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Stephanie Greaves", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/340/"}], "functions": {"diagram": {"definition": "var xconstraint=Xforecast-Xstock;\nvar yconstraint=Yforecast-Ystock;\nvar xboundA=(Atime*60-YtimeA*(yconstraint))/XtimeA+5;\nvar xboundB=(Btime*60-YtimeB*(yconstraint))/XtimeB+5;\nvar te=(xboundA >=xboundB);\nvar xbound=Math.max(xboundA,xboundB);\nvar yboundA=(Atime*60-XtimeA*(xconstraint))/YtimeA+5;\nvar yboundB=(Btime*60-XtimeB*(xconstraint))/YtimeB+5;\nvar te1=(yboundA >=yboundB);\nvar ybound=xbound;\nvar solpt;\nvar solx;\nvar soly;\nvar stockleft=-xconstraint-yconstraint;\nvar Afunction=function(x){return (Atime*60-XtimeA*x)/YtimeA;};\nvar Bfunction=function(x){return (Btime*60-XtimeB*x)/YtimeB;};\nvar SLfunction=function(x,y){return x+y+stockleft;};\nvar pt;\nvar div = Numbas.extensions.jsxgraph.makeBoard('400px','400px',\n{boundingBox:[-1,ybound,xbound,-10],\n axis:true,\n showNavigation:false,\n grid:true});\nvar brd=div.board;\n//Create lines using homogeneous coordinates - beware,ax+by+c=0\n//is entered as [c,a,b]\nvar Bline=brd.create('line',[-60*Btime,XtimeB,YtimeB],{name:'Machine B',withLabel:true,fixed:true});\nvar Aline=brd.create('line',[-60*Atime,XtimeA,YtimeA],{name:'Machine A',withLabel:true,fixed:true});\nvar ep=brd.create('intersection',[Aline,Bline],{name:'T',withLabel:true,face:'x',fixed:true});\n\nvar xconst=brd.create('segment',[[xconstraint,0],[xconstraint,ybound]],{strokeColor:'red',fixed:true});\nvar yconst=brd.create('segment',[[0,yconstraint],[xbound,yconstraint]],{strokeColor:'red',fixed:true});\n\nvar al=brd.create('point',[xconstraint,yconstraint],{name:'P',face:'x',fixed:true});\nvar be;\nvar ga;\nvar machine;\nif(te)\n {be=brd.create('point',[xboundA-5,yconstraint],{name:'Q',face:'x',fixed:true});}\nelse \n {be=brd.create('point',[xboundB-5,yconstraint],{name:'Q',face:'x',fixed:true});}\nif(te1)\n{ga=brd.create('point',[xconstraint,Afunction(xconstraint)],{name:'R',face:'x',fixed:true});}\nelse\n {ga=brd.create('point',[xconstraint,Bfunction(xconstraint)],{name:'R',face:'x',fixed:true});}\n//var del=brd.create('point',[xconstraint,Bfunction(xconstraint)],{name:'S',face:'x',fixed:true});\nif(!te&& te1){\n brd.create('polygon',[al,be,ep,ga],{name:\"Feasible Region\",withLabel:false});}\n \n else{\n brd.create('polygon',[al,be,ga],{name:\"Feasible Region\",withLabel:false});\n }\nif(SLfunction(be.X(),be.Y())>SLfunction(ga.X(),ga.Y()))\n {solx=be.X();soly=be.Y();pt='Q';if(te){machine='A';} else {machine='B';}}\nelse \n{solx=ga.X();soly=ga.Y();pt='R';if(te1){machine='A';} else {machine='B';}}\n \n\nsolx=Numbas.math.precround(Numbas.math.niceNumber(solx),1);\nsoly=Numbas.math.precround(Numbas.math.niceNumber(soly),1);\nvar s=brd.create('slider',[[5, 5], [15,5], [0, solx+soly-(xconstraint+yconstraint), 100]],{name:'Stock left'});\nvar st=brd.create('line',[function(){return (-xconstraint-yconstraint)-s.Value();},1,1],{strokeColor:'green',dash:1,name:'Stock left',withLabel:true});\nvar t1 = brd.create('text',[0,-7,\"solutions:x= \"+solx+\",y= \"+soly]);\n$('#xsol').text(solx);\n$('#ysol').text(soly);\nstockleft=Numbas.math.precround(Numbas.math.niceNumber(solx+soly-(xconstraint+yconstraint)),1);\n$('#stckleft').text(stockleft);\n$('#ptname').text(pt);\n$('#machine').text(machine);\nreturn div;\n", "type": "html", "language": "javascript", "parameters": [["XtimeA", "number"], ["YtimeA", "number"], ["XtimeB", "number"], ["YtimeB", "number"], ["Xstock", "number"], ["Ystock", "number"], ["Atime", "number"], ["Btime", "number"], ["Xforecast", "number"], ["Yforecast", "number"]]}, "userinput": {"definition": "\nvar xconstraint=Xforecast-Xstock;\nvar yconstraint=Yforecast-Ystock;\nvar xboundA=(Atime*60-YtimeA*(yconstraint))/XtimeA+5;\nvar xboundB=(Btime*60-YtimeB*(yconstraint))/XtimeB+5;var yboundA=(Atime*60-XtimeA*(xconstraint))/YtimeA+5;\nvar yboundB=(Btime*60-XtimeB*(xconstraint))/YtimeB+5;\nvar xbound=Math.max(xboundA,xboundB,yboundA,yboundB);\nvar ybound=xbound;\nvar div = Numbas.extensions.jsxgraph.makeBoard('400px','400px',{\n boundingBox:[-1,ybound,xbound,-5],\n axis:true,\n showNavigation:false,\n grid:true\n});\nvar board=div.board;\nvar s=board.create('slider',[[5, 5], [15,5], [0, 0, 50]],{name:'Stock left'});\nvar stockleft=-xconstraint-yconstraint;\nvar st=board.create('segment',[[function(){return -stockleft+s.Value();},0],[0,function(){return -stockleft+s.Value();}]],{strokeColor:'green',dash:1,name:'Stock left',withLabel:true});\nquestion.signals.on('HTMLAttached',function(e) {\n \n //set up KO observables to compute the coordinates from the student's input\n var xcon = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[0].display.studentAnswer());\n });\n var ycon = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[1].display.studentAnswer());\n });\n var aa = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[2].display.studentAnswer());\n });\n var ba = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[3].display.studentAnswer());\n });\n var ca = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[4].display.studentAnswer());\n });\n var ta_coordinates = ko.computed(function() {\nif(isNaN(aa()) || isNaN(ba()) || isNaN(ca())) {\n // return [0,0,1];\n}\nreturn [-ca(),aa(),ba()];\n });\n \n // create the lines\n var x_constraint_line = board.create('line',[[xcon,0],[xcon,1]],{strokeColor:'red',fixed:true, straightFirst: false});\n var y_constraint_line = board.create('line',[[0,ycon],[1,ycon]],{strokeColor:'red',fixed:true, straightFirst: false});;\n var inequality_linea = board.create('line',[ta_coordinates]);\n var ab = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[5].display.studentAnswer());\n });\n var bb = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[6].display.studentAnswer());\n });\n var cb = ko.computed(function() {\nreturn parseFloat(question.parts[0].gaps[7].display.studentAnswer());\n });\n var tb_coordinates = ko.computed(function() {\nif(isNaN(ab()) || isNaN(bb()) || isNaN(cb())) {\n // return [0,0,1];\n}\nreturn [-cb(),ab(),bb()];\n });\n \n var inequality_lineb = board.create('line',[tb_coordinates]);\n var ep=board.create('intersection',[inequality_linea,inequality_lineb],{name:'T',face:'x',visible:false});\n var al=board.create('point',[xcon,ycon],{name:'P',face:'x',fixed:true});\n var be1=board.create('intersection',[inequality_linea,y_constraint_line],{name:'Q',face:'x',fixed:true,visible:false});\n var be2=board.create('intersection',[inequality_lineb,y_constraint_line],{name:'Q',face:'x',fixed:true,visible:false});\n var ga=board.create('intersection',[x_constraint_line,inequality_linea],{name:'R',face:'x',fixed:true,visible:false});\n var del=board.create('intersection',[x_constraint_line,inequality_lineb],{name:'R',face:'x',fixed:true,visible:false});\n var fr1=board.create('polygon',[al,be2,ep,ga],{name:\"Feasible Region\",visible:false}); \n var fr2=board.create('polygon',[al,be1,ga],{name:\"Feasible Region\",visible:false}); \n var fr3=board.create('polygon',[al,be2,del],{name:\"Feasible Region\",visible:false}); \n ko.computed(function(){ \n// look at the observables, so this function gets called whenever they change\nxcon(),ycon(),ta_coordinates(),tb_coordinates();\n\nvar lineAOK=!(isNaN(aa()) || isNaN(ba()) || isNaN(ca()));\nvar lineBOK=!(isNaN(ab()) || isNaN(bb()) || isNaN(cb()));\nvar consxOK= !isNaN(xcon());var consyOK= !isNaN(ycon());\n// show/hide the lines based on whether the student input is valid\nvar te=(be1.X()> be2.X());\nvar te1=(ga.Y()> del.Y());\nx_constraint_line.setAttribute({'visible':consxOK});\ny_constraint_line.setAttribute({'visible': consyOK}); \ninequality_linea.setAttribute({'visible': lineAOK});\ninequality_lineb.setAttribute({'visible': lineBOK});\nal.setAttribute({'visible':consxOK&&consyOK});\nep.setAttribute({'visible':((lineAOK&&lineBOK))&&((!te)&&te1)});\nbe1.setAttribute({'visible':lineAOK&&te});\nbe2.setAttribute({'visible':lineBOK&&(!te)});\nga.setAttribute({'visible':(lineAOK&&consxOK)&&te1});\ndel.setAttribute({'visible':(lineBOK&&consxOK)&&(!te1)}); \nvar fr1_visible = ((consxOK&&consyOK)&&(lineAOK&&lineBOK))&&((!te)&&te1);\nvar fr2_visible = consxOK&&consyOK&&lineAOK&&lineBOK&&te&&te1;\nvar fr3_visible = consxOK&&consyOK&&lineAOK&&lineBOK&&(!te)&&(!te1);\nfr1.setAttribute({'visible':fr1_visible, 'fillOpacity': fr1_visible ? 0.3 : 0});\nfr2.setAttribute({'visible':fr2_visible, 'fillOpacity': fr2_visible ? 0.3 : 0}); \nfr3.setAttribute({'visible':fr3_visible, 'fillOpacity': fr3_visible ? 0.3 : 0}); \n// prompt JSXGraph to reevaluate the coordinate functions\nboard.update(); \n }); \n});\n\nreturn div;\n", "type": "html", "language": "javascript", "parameters": [["XtimeA", "number"], ["YtimeA", "number"], ["XtimeB", "number"], ["YtimeB", "number"], ["Xstock", "number"], ["Ystock", "number"], ["Atime", "number"], ["Btime", "number"], ["Xforecast", "number"], ["Yforecast", "number"]]}}, "ungrouped_variables": ["yconstraint", "xstock", "xforecast", "xtimea", "atime", "xtimeb", "xconstraint", "btime", "timeforb", "r1", "timefora", "r2", "ytimeb", "ystock", "ytimea", "yforecast"], "tags": ["Feasible region", "Jsxgraph", "constraints", "graphical method", "jsxgraph", "linear programming", "maximise", "objective function"], "preamble": {"css": "", "js": ""}, "advice": "{diagram(xtimea,ytimea,xtimeb,ytimeb,xstock,ystock,atime,btime,xforecast,yforecast)}
\nThe constraints are:
\n$\\var{xtimea}x + \\var{ytimea}y \\leq \\var{atime}\\times 60 =\\var{atime*60}$ machine A time.
\n$\\var{xtimeb}x + \\var{ytimeb}y \\leq \\var{btime}\\times 60 =\\var{btime*60}$ machine B time.
\n$x \\geq \\var{xforecast} -\\var{xstock}=\\var{xforecast-Xstock}$
\nThis ensures that production of bicycles $\\geq$ demand ($\\var{xforecast}$) - initial stock ($\\var{xstock}$) and so meets demand.
\n$y \\geq \\var{yforecast} -\\var{ystock}=\\var{yforecast-ystock}$.
\nThis ensures that production of scooters $\\geq$ demand ($\\var{yforecast}$) - initial stock ($\\var{ystock}$) and so meets demand.
\nThe objective is: maximise $(x+\\var{xstock}-\\var{xforecast}) + (y+\\var{ystock}-\\var{yforecast}) = \\simplify{x+y+{xstock+ystock-xforecast-yforecast}}$
i.e. to maximise the number of units left in stock at the end of the week
The Feasible region is the green area and we have moved the Stock left objective function line to the position where it intersects the Feasible region and maximises Stock left.
\nWe find using the graphical method that using Machine : $x=\\;$, $y=\\;$, Stock left =
\nThis occurs at the point in the above diagram.
\nYour graphical solution may differ slightly from these as it is not always possible to get the objective line accurately through the desired point. Also, if these numbers are not whole numbers then you can easily find a whole number solution near these and any such reasonable solution near the above solutions is fine as long as it lies in the Feasible region.
", "rulesets": {}, "parts": [{"prompt": "Let $x,\\;y$ be the number of bicycles and scooters produced respectively.
\n{userinput(xtimea,ytimea,xtimeb,ytimeb,xstock,ystock,atime,btime,xforecast,yforecast)}
\nWhat are the constraints on production given the forecasts for bicycles and scooters and the stock levels?
\n$x \\ge\\;$[[0]] $y \\ge\\;$[[1]]
\nTime inequality for Machine A: [[2]]$x\\;+\\;$[[3]]$y\\;\\le\\;$[[4]] (in minutes)
\nTime inequality for Machine B: [[5]]$x\\;+\\;$[[6]]$y\\;\\le\\;$[[7]] (in minutes)
\nInput the objective function which maximises Stock left.
\nObjective function: [[8]]
\nNote that the objective function Stock left is displayed above for the values of $x$ and $y$ which just clear demand i.e. Stock left=0. Once you have input all of the constraints you can use the slider to move the objective function to the value of $x$ and $y$ in the Feasible region to maximise Stock left.
\nUsing this diagram find values of the production of $x$ and $y$ which satisfy the constraints and maximise the amount of stock $x+y$ left at the end of the week.
\n", "marks": 0, "gaps": [{"allowFractions": false, "marks": 1, "maxValue": "xconstraint", "minValue": "xconstraint", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "yconstraint", "minValue": "yconstraint", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "xtimea", "minValue": "xtimea", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "ytimea", "minValue": "ytimea", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "atime*60", "minValue": "atime*60", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "xtimeb", "minValue": "xtimeb", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "ytimeb", "minValue": "ytimeb", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"allowFractions": false, "marks": 1, "maxValue": "btime*60", "minValue": "btime*60", "correctAnswerFraction": false, "showCorrectAnswer": true, "scripts": {}, "type": "numberentry", "showPrecisionHint": false}, {"vsetrangepoints": 5, "expectedvariablenames": [], "checkingaccuracy": 0.001, "vsetrange": [0, 1], "showpreview": true, "marks": 1, "showCorrectAnswer": true, "answersimplification": "all", "scripts": {}, "answer": "x+y-{xconstraint+yconstraint}", "checkingtype": "absdiff", "checkvariablenames": false, "type": "jme"}], "showCorrectAnswer": true, "scripts": {}, "type": "gapfill"}], "statement": "A company makes two products (bicycles and scooters) using two machines (A and B).
\nEach bicycle that is produced requires $\\var{XtimeA}$ minutes processing time on machine A and $\\var{XtimeB}$ minutes processing time on machine B.
\nEach scooter that is produced requires $\\var{YtimeA}$ minutes processing time on machine A and $\\var{YtimeB}$ minutes processing time on machine B.
\nEither Machine A or Machine B will be used given there is only one available operator.
\nAt the start of the current week there are $\\var{Xstock}$ bicycles and $\\var{Ystock}$ scooters in stock.
\nAvailable processing time on machine A is forecast to be $\\var{Atime}$ hours and on machine B is forecast to be $\\var{Btime}$ hours.
\nThe demand for bicycles in the current week is forecast to be $\\var{Xforecast}$ units and for scooters is forecast to be $\\var{Yforecast}$ units.
\nCompany policy is to maximise the combined sum of the units of bicycles and the units of scooters in stock at the end of the week.
\n(Author of original problem: J E Beasley: http://people.brunel.ac.uk/~mastjjb/jeb/or/rights.html)
", "variable_groups": [], "variablesTest": {"maxRuns": 100, "condition": ""}, "variables": {"yconstraint": {"definition": "\n//Difference between forecast demand and stock, \n//so more than this have to be created to meet demand .\nrandom(6..15)\n", "templateType": "anything", "group": "Ungrouped variables", "name": "yconstraint", "description": ""}, "xstock": {"definition": "\n//Amount in stock for X at beginning of week\nrandom(10..40)\n", "templateType": "anything", "group": "Ungrouped variables", "name": "xstock", "description": ""}, "xforecast": {"definition": "xconstraint+xstock", "templateType": "anything", "group": "Ungrouped variables", "name": "xforecast", "description": ""}, "xtimea": {"definition": "random(50..100)", "templateType": "anything", "group": "Ungrouped variables", "name": "xtimea", "description": ""}, "yforecast": {"definition": "yconstraint+ystock", "templateType": "anything", "group": "Ungrouped variables", "name": "yforecast", "description": ""}, "ystock": {"definition": "\n//Amount in stock for Y at beginning of week\nrandom(70..100)\n", "templateType": "anything", "group": "Ungrouped variables", "name": "ystock", "description": ""}, "xconstraint": {"definition": "\n//Difference between forecast demand and stock, \n//so more than this have to be created to meet demand .\nrandom(30..60)\n", "templateType": "anything", "group": "Ungrouped variables", "name": "xconstraint", "description": ""}, "btime": {"definition": "\n//time buffer for Machine B (in hours).\n//if you add on a small number of hours on timeforb then you \n//will restrict the feasible area.\nround((timeforb+random(500..1000))/60)\n", "templateType": "anything", "group": "Ungrouped variables", "name": "btime", "description": ""}, "timeforb": {"definition": "\n//least amount of time that Machine B has to work.\nxconstraint*xtimeb+yconstraint*ytimeb\n", "templateType": "anything", "group": "Ungrouped variables", "name": "timeforb", "description": ""}, "r1": {"definition": "\n//slope of line for Machine A\nrandom(2.0..3.0#0.05)\n", "templateType": "anything", "group": "Ungrouped variables", "name": "r1", "description": ""}, "timefora": {"definition": "\n//least amount of time that Machine A has to work.\nxconstraint*xtimea+yconstraint*ytimea\n", "templateType": "anything", "group": "Ungrouped variables", "name": "timefora", "description": ""}, "r2": {"definition": "\n//slope of line for Machine B, less than that for Machine A\nrandom(0.3..1.5#0.05 except 1.0)\n", "templateType": "anything", "group": "Ungrouped variables", "name": "r2", "description": ""}, "ytimeb": {"definition": "round(xtimeb/r2)", "templateType": "anything", "group": "Ungrouped variables", "name": "ytimeb", "description": ""}, "atime": {"definition": "\n//time buffer for Machine A (in hours).\n//if you add on a small number of hours to timefora then you \n//will restrict the feasible area.\nround((timefora+random(500..1000))/60)\n", "templateType": "anything", "group": "Ungrouped variables", "name": "atime", "description": ""}, "ytimea": {"definition": "\n//ensures slope is approx r1\nround(xtimea/r1)\n", "templateType": "anything", "group": "Ungrouped variables", "name": "ytimea", "description": ""}, "xtimeb": {"definition": "random(25..50)", "templateType": "anything", "group": "Ungrouped variables", "name": "xtimeb", "description": ""}}, "metadata": {"notes": "05/01/2014:
\nFirst version finished with functions supplied by CP.
\nDisplay needs improving.
", "description": "Graphical linear program example. Two machines both producing the same 2 products with varying times of production for each product and time constraints on machine use in a week. Given stock at the beginning of the week together with a forecast demand to be met, find production which maximises stock at the end of the week.
\n(Author of original problem: J E Beasley: http://people.brunel.ac.uk/~mastjjb/jeb/or/rights.html)
", "licence": "None specified"}, "type": "question", "showQuestionGroupNames": false, "question_groups": [{"name": "", "pickingStrategy": "all-ordered", "pickQuestions": 0, "questions": []}]}], "pickQuestions": 0}], "navigation": {"onleave": {"action": "none", "message": ""}, "reverse": true, "allowregen": true, "preventleave": true, "browse": true, "showfrontpage": true, "showresultspage": "never"}, "duration": 0, "metadata": {"notes": "", "description": "Questions on linear programming techniques, with interactive graphics.
", "licence": "Creative Commons Attribution 4.0 International"}, "allQuestions": true, "shuffleQuestions": false, "questions": [], "percentPass": 0, "timing": {"allowPause": true, "timeout": {"action": "none", "message": ""}, "timedwarning": {"action": "none", "message": ""}}, "pickQuestions": 0, "type": "exam", "showQuestionGroupNames": false, "feedback": {"showtotalmark": true, "advicethreshold": 0, "showanswerstate": true, "showactualmark": true, "allowrevealanswer": true}, "contributors": [{"name": "Denis Flynn", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/1216/"}], "extensions": ["jsxgraph", "stats"], "custom_part_types": [], "resources": []}