{"id":201,"date":"2014-12-01T12:00:49","date_gmt":"2014-12-01T01:00:49","guid":{"rendered":"http:\/\/scipilot.org\/blog\/?p=201"},"modified":"2015-01-06T22:02:30","modified_gmt":"2015-01-06T11:02:30","slug":"cutlass-cut-less","status":"publish","type":"post","link":"https:\/\/scipilot.org\/blog\/2014\/12\/01\/cutlass-cut-less\/","title":{"rendered":"Cutlass &#8211; Cut Less!"},"content":{"rendered":"<p>While re-building my house I became obsessed with getting efficiency out of the timber 10materials I was using when planning cutting lists.\u00a0Most people would want to achieve an efficient cutting plan\u00a0because of cost-efficiency, effort-reduction or ecological\u00a0conservation, and of course that was true for me but being a huge nerd I was even more intrigued by the\u00a0devilishly difficult planning problem itself. Surely an algorithm could be produced to make cutting lists easy to produce, and thereby save enormous amounts of trees?<\/p>\n<p>So what&#8217;s the problem?<\/p>\n<h2>The Problem<\/h2>\n<p>Well I have a) a long list of measured lengths to make tongue and grooved lining boards fit horizontally around our many doors and windows and b) a bunch of raw timber in standard lengths. The challenge is to cut the timber so the waste offcut each time can also be used.<\/p>\n<p><a href=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-Stock-Illustration1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-203\" src=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-Stock-Illustration1.png\" alt=\"Cutlass Stock Illustration\" width=\"664\" height=\"299\" srcset=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-Stock-Illustration1.png 664w, https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-Stock-Illustration1-300x135.png 300w\" sizes=\"auto, (max-width: 664px) 100vw, 664px\" \/><\/a><\/p>\n<h2>The Solutions<\/h2>\n<p>The woodyard-recommended\u00a0solution is to order 10% more timber than you need and hope.\u00a0Then you just throw away the waste. Of course they <em>would<\/em> recommend you spend 10% more, but I just don&#8217;t find this an acceptable attitude.<\/p>\n<p>After trying to figure out a process myself for three complex rooms and 150m of timber I\u00a0almost had a brain meltdown, I did some research into online tools and then common algorithms. Of course this is a\u00a0very\u00a0old problem!<\/p>\n<p>At first I researched the &#8220;cutting stock problem&#8221; but this is mostly oriented towards reducing waste from cutting 2D sheets of fabric, timber or metal and incorporates complex requirements like reducing knife-changing interruptions.<\/p>\n<p>I found it difficult to find a 1D cutting algorithm, until I came across the &#8220;bin packing problem&#8221;, which is functionally equivalent to this problem. All you have to do is tilt your head on one side, and view the &#8216;bins&#8217; as\u00a0the original stock and the vertical heights of the objects being placed in the bins as the planned lengths required.<\/p>\n<p><a href=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-Stock-Illustration-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-204\" src=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-Stock-Illustration-1.png\" alt=\"Cutlass Stock Illustration (1)\" width=\"279\" height=\"173\" \/><\/a><\/p>\n<p>The first-fit algorithm is pretty simple: you find\u00a0the next longest length in\u00a0your requirement\u00a0plan and take that away from the first stock with enough left (i.e. put it in the first bin). Repeat.<\/p>\n<p>It&#8217;s not guaranteed to find the <em>overall<\/em> best usage\u00a0for all items. In theory, if you tried all possible combinations you could probably get a lot more zero-waste planks, but this sounds like one of those more-atoms-than-the-universe scenarios to me. I might add some level of re-try to it later or do more research into simultaneous equations, which I suspect could offer\u00a0a solution.<\/p>\n<h2>My Implementation<\/h2>\n<p>Of course programming this will have a few more practical details like initially sorting the required lengths and handling problems like running out of stock, but that&#8217;s the basic algorithm. So I cracked open a new Bootstrap theme and wrote it in Javascript to avoid any unnecessary back-end requirements:<\/p>\n<pre>\/*\r\n * Best fit tries to fill the available slots with the minimum remaining.\r\n * Slots are only brought online when no previous slots can be fitted into.\r\n * You start with one slot online, and put the first item into it.\r\n *\/\r\nbestFitAlgorithm: function(aTimberList, aCuttingList){\r\n  \/\/ first we assume there's only one entry in the timber list - phase one!\r\n  var iPlankSize = aTimberList[0][0];\r\n  var iNoPlanks = aTimberList[0][1];\r\n  var aPlanks = [];\r\n  var count, len, min, p, remaining;\r\n\r\n  \/\/ iterate over the required lengths\r\n  for(var i in aCuttingList){\r\n    len = aCuttingList[i][0];\r\n    count = aCuttingList[i][1];\r\n    while(count--){\r\n      \/\/ Check all online planks in order\r\n      min = iPlankSize;\r\n      p = null;\r\n      for(var j in aPlanks){\r\n        remaining = aPlanks[j].remaining - len;\r\n        if(remaining &gt;= 0 &amp;&amp; remaining &lt; min){\r\n           min = remaining;\r\n          p = j;\r\n        }\r\n      }\r\n      if(p != null){\r\n        \/\/ p is the best fit.\r\n         aPlanks[p].remaining = min;\r\n        aPlanks[p].pieces.push(len);\r\n      }\r\n      else {\r\n        \/\/ No fit found, bring another plank online\r\n        aPlanks.push({remaining:iPlankSize-len, pieces:[len]});\r\n      }\r\n    }\r\n  }\r\n  return aPlanks;\r\n}<\/pre>\n<p>I surrounded this with some self-unit-testing, a JQuery plugin wrapper and a basic form UI to talk to the humans, and went to work.<\/p>\n<h2>The Real World Beta Test &#8211; My Lining Boards<\/h2>\n<p>The plan\u00a0that I actually needed was as follows, with length of item in mm (len) and how many\u00a0(off).<\/p>\n<pre>len  off\r\n3100 2\r\n2900 1\r\n360 1\r\n305 16\r\n1300 2\r\n245 13\r\n3740 4\r\n440 8\r\n1070 1\r\n190 7\r\n900 1\r\n4000 2\r\n3820 5\r\n140 9\r\n110 15\r\n1200 2\r\n230 15\r\n120 15\r\n1450 23\r\n500 15\r\n2820 1\r\n120 15\r\n380 15\r\n200 9\r\n1150 3\r\n1150 6\r\n140 9\r\n1270 18<\/pre>\n<p>My stock was 5400mm lengths of pre-primed T&amp;G grooved panelling. The algorithm\u00a0came up with the following cutting list, where the first number is the stock plank index, then the length to cut and finally the waste.<\/p>\n<p>I added a default 3mm kerf (the width of the cut made by the saw) which is easy to forget when planning cuts and soon adds up to a significant amount\u00a0&#8211; especially when you are trying to achieve near zero-wastage with many small pieces (see bottom planks).<\/p>\n<pre id=\"results\">0: 4000,1300 waste:100\r\n1: 4000,1300 waste:100\r\n2: 3820,1450,120 waste:10\r\n3: 3820,1450,120 waste:10\r\n4: 3820,1450,120 waste:10\r\n5: 3820,1450,120 waste:10\r\n6: 3820,1450,120 waste:10\r\n7: 3740,1450,200 waste:10\r\n8: 3740,1450,200 waste:10\r\n9: 3740,1450,200 waste:10\r\n10: 3740,1450,200 waste:10\r\n11: 3100,1450,500,305 waste:45\r\n12: 3100,1450,500,305 waste:45\r\n13: 2900,1450,900,140 waste:10\r\n14: 2820,1450,1070 waste:60\r\n15: 1450,1450,1450,500,500 waste:50\r\n16: 1450,1450,1450,500,500 waste:50\r\n17: 1450,1450,1450,500,500 waste:50\r\n18: 1450,1270,1270,1270,140 waste:0\r\n19: 1270,1270,1270,1270,305 waste:15\r\n20: 1270,1270,1270,1270,305 waste:15\r\n21: 1270,1270,1270,1270,305 waste:15\r\n22: 1270,1270,1270,1200,380 waste:10\r\n23: 1200,1150,1150,1150,500,245 waste:5\r\n24: 1150,1150,1150,1150,500,245 waste:55\r\n25: 1150,1150,500,500,500,500,500,440,140 waste:20\r\n26: 440,440,440,440,440,440,440,380,380,380,380,380,380 waste:40\r\n27: 380,380,380,380,380,380,380,380,360,305,305,305,305,305,305,140 waste:30\r\n28: 305,305,305,305,305,245,245,245,245,245,245,245,245,245,245,245,230,230,230,230,230 waste:30\r\n29: 230,230,230,230,230,230,230,230,230,230,200,200,200,200,200,190,190,190,190,190,190,190,140,140,140,140,140 waste:70\r\n30: 140,140,140,140,140,140,140,140,140,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,110,110,110,110,110,110,110,110,110,110 waste:40\r\n31: 110,110,110,110,110 waste:4850\r\n\r\nTotal timber length: 167005\r\nTotal waste:5795\r\nPercentace waste:3.47%<\/pre>\n<p>So that was pretty impressive 3.5% wastage which is a third of the accepted industry standard.<\/p>\n<p>In theory!<\/p>\n<div id='gallery-1' class='gallery galleryid-201 gallery-columns-2 gallery-size-medium'><dl class='gallery-item'>\n\t\t\t<dt class='gallery-icon landscape'>\n\t\t\t\t<a href='https:\/\/scipilot.org\/blog\/2014\/12\/01\/cutlass-cut-less\/cutlass-in-action-stock\/'><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"225\" src=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-stock-300x225.jpg\" class=\"attachment-medium size-medium\" alt=\"\" aria-describedby=\"gallery-1-209\" srcset=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-stock-300x225.jpg 300w, https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-stock-1024x768.jpg 1024w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>\n\t\t\t<\/dt>\n\t\t\t\t<dd class='wp-caption-text gallery-caption' id='gallery-1-209'>\n\t\t\t\tThe stock &#8211; 160m of white plane lining boards, 50m of blue regency beaded (for a curved ceiling) and another 100m of architrave.\n\t\t\t\t<\/dd><\/dl><dl class='gallery-item'>\n\t\t\t<dt class='gallery-icon landscape'>\n\t\t\t\t<a href='https:\/\/scipilot.org\/blog\/2014\/12\/01\/cutlass-cut-less\/cutlass-in-action-1\/'><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"225\" src=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-1-300x225.jpg\" class=\"attachment-medium size-medium\" alt=\"\" aria-describedby=\"gallery-1-208\" srcset=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-1-300x225.jpg 300w, https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-1-1024x768.jpg 1024w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>\n\t\t\t<\/dt>\n\t\t\t\t<dd class='wp-caption-text gallery-caption' id='gallery-1-208'>\n\t\t\t\tThe architrave cutting list &#8211; with the beginnings of phase2 requirements for tracking the progress of the cuts\n\t\t\t\t<\/dd><\/dl><br style=\"clear: both\" \/><dl class='gallery-item'>\n\t\t\t<dt class='gallery-icon landscape'>\n\t\t\t\t<a href='https:\/\/scipilot.org\/blog\/2014\/12\/01\/cutlass-cut-less\/cutlass-in-action-2\/'><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"225\" src=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-2-300x225.jpg\" class=\"attachment-medium size-medium\" alt=\"\" aria-describedby=\"gallery-1-207\" srcset=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-2-300x225.jpg 300w, https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-2-1024x768.jpg 1024w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>\n\t\t\t<\/dt>\n\t\t\t\t<dd class='wp-caption-text gallery-caption' id='gallery-1-207'>\n\t\t\t\tExample of the complexity of the measurements!\n\t\t\t\t<\/dd><\/dl><dl class='gallery-item'>\n\t\t\t<dt class='gallery-icon landscape'>\n\t\t\t\t<a href='https:\/\/scipilot.org\/blog\/2014\/12\/01\/cutlass-cut-less\/cutlass-in-action-3\/'><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"225\" src=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-3-300x225.jpg\" class=\"attachment-medium size-medium\" alt=\"\" aria-describedby=\"gallery-1-206\" srcset=\"https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-3-300x225.jpg 300w, https:\/\/scipilot.org\/blog\/wp-content\/uploads\/2015\/01\/Cutlass-in-action-3-1024x768.jpg 1024w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>\n\t\t\t<\/dt>\n\t\t\t\t<dd class='wp-caption-text gallery-caption' id='gallery-1-206'>\n\t\t\t\tExample of the variation of lengths.\n\t\t\t\t<\/dd><\/dl><br style=\"clear: both\" \/>\n\t\t<\/div>\n\n<h2>The Messy Real World<\/h2>\n<p>When I actually got cutting with my proudly printed-out list, I discovered a few &#8220;real world&#8221; shortcomings.<\/p>\n<ol>\n<li><strong>Job planning:<\/strong> My initial list was ordered in a real-world sequence from room to room, making it easy to follow while you work from the floor-up (grooves into tongues), and around window features etc. However the algorithm had scattered the pieces all over the stock planks, meaning I had to a) track them down in the list, b) &#8216;open&#8217; up a stock plank by cutting out that one length, c) keep track of the remaining stock with chalk\/tape\/pencil which is physically challenging in a small house and 160m of timber!<\/li>\n<li><strong>Mistakes:<\/strong> I had mis-measured a couple of items in my plan! This meant the whole cutting list was wrong and needed updating. So surely a quick re-run through the algorithm? No, because I was now half way through the cutting process and had already cut several planks, so the stock was now of various sizes. Well, I had planned this as a feature for phase-2 but I had taken the kitchen apart and was all covered in sawdust and sweat and wasn&#8217;t about to stop and do a couple of hours programming!<\/li>\n<li><strong>Timber quality:<\/strong>\u00a0no timber\u00a0stock is perfect (even DAR or this pre-primed luxury). Sometimes it gets knocked, dented or a knot pops. So again we need to be able to discard a piece, and re-run the algorithm as per 2).<\/li>\n<li><strong>Other similar problems:<\/strong>\u00a0leading to the need for flexibility, better planning and keeping tally on progress and stock\/inventory. Often your plan changes while you&#8217;re doing carpentry as you work around issues or get into the detail (we have sloping ceilings and other oddities) which just needs a hands-on decision.<\/li>\n<\/ol>\n<h2>Being the Computer<\/h2>\n<p>Of course all of these things could be resolved in phase 2, but to finish the project I actually ran the algorithm myself:<\/p>\n<ul>\n<li>Select the next <em>longest<\/em> item in the (current room\/job&#8217;s) plan<\/li>\n<li>Select the <em>shortest<\/em> stock which this can be cut from<\/li>\n<li>Cut it, re-measure and write the measurement <em>on the stock<\/em>. (This is essentially an index, as you will be reading this measurement many times as you iterate through the stock and it means you can keep the timber stacked which makes it difficult to measure).<\/li>\n<\/ul>\n<p>This is effectively what experienced carpenters do anyway &#8211; I found out later from my father-in-law! But from a craftsman perspective it&#8217;s reassuring\u00a0to know that a rule of thumb is far\u00a0more <em>practically effective<\/em> than an algorithm based on advanced mathematical theory and these\u00a0new-fangled computers.<\/p>\n<h2>DIY!<\/h2>\n<p>Try out (the alpha version) for yourself here:\u00a0<a href=\"http:\/\/scipilot.org\/cutlass\">http:\/\/scipilot.org\/cutlass<\/a><\/p>\n<h2>Lessons<\/h2>\n<p>While I would like to work on phase 2, I don&#8217;t have any major carpentry projects planned at the moment, so I predict lack of necessity will mean this project may sadly stagnate.<\/p>\n<p>However I really think this real-world problem would be a great tutorial or project for a software-engineering\u00a0course.<\/p>\n<ul>\n<li>It encapsulates a very difficult problem with potentially fun mathematical depth,<\/li>\n<li>it has\u00a0no perfect solution which is a reality young programmers have to face,<\/li>\n<li>it highlights some real-world complexities requiring good UI\/UX to prevent the wonderful maths being totally useless practically<\/li>\n<li>and finally it would benefit from expert-interviews (stakeholder input)<\/li>\n<\/ul>\n<p>i.e. by talk to your father in-law <span style=\"text-decoration: underline;\">before<\/span> starting a hair-brained\u00a0programming project!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>While re-building my house I became obsessed with getting efficiency out of the timber 10materials I was using when planning cutting lists.\u00a0Most people would want to achieve an efficient cutting plan\u00a0because of cost-efficiency, effort-reduction or ecological\u00a0conservation, and of course that &hellip; <a href=\"https:\/\/scipilot.org\/blog\/2014\/12\/01\/cutlass-cut-less\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17,3],"tags":[25,44,24,36],"class_list":["post-201","post","type-post","status-publish","format-standard","hentry","category-articles","category-projects","tag-foss","tag-javascript","tag-library","tag-programming"],"_links":{"self":[{"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/posts\/201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/comments?post=201"}],"version-history":[{"count":4,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/posts\/201\/revisions"}],"predecessor-version":[{"id":212,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/posts\/201\/revisions\/212"}],"wp:attachment":[{"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/media?parent=201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/categories?post=201"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scipilot.org\/blog\/wp-json\/wp\/v2\/tags?post=201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}