tag:blogger.com,1999:blog-6422447884695587452018-05-05T23:57:37.449+03:00Garden Path Trajectory Algorithms, Math Education, and the Art of Doing the Dishes Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-642244788469558745.post-71081736395298732802018-02-21T22:41:00.000+02:002018-02-21T22:41:11.344+02:00Hierarchical Hierarchical Clustering: A Concept So Nice, We Named It TwiceWhile working at <a href="https://www.resonai.com/">Resonai</a>, I wrote a piece of code that performs <a href="https://en.wikipedia.org/wiki/Hierarchical_clustering">Hierarchical Clustering</a>, in collaboration with <a href="https://www.linkedin.com/in/david-lehavi-418b1a3/">David Lehavi</a>. In addition to various optimizations I won't get into, we applied a nice heuristic that allowed a considerable improvement in the program's memory footprint, as well as the running time. The more formal name we gave it was <i>Spatially Sensitive Hierarchical Clustering</i> (SSHC), but ended up referring to it as <i>Hierarchical Hierarchical Clustering </i>which is funnier, and better reflects what's really going on.<br /><br /><h3>Hierarchical Clustering in a Nutshell</h3><div>The following image, taken from the Wikipedia article on HC, illustrates the basic notion rather well:</div><div><br /></div><div><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/Hierarchical_clustering_simple_diagram.svg/418px-Hierarchical_clustering_simple_diagram.svg.png" /></div><div><br /></div><div>Suppose we have 6 items that we wish to cluster, and we have some metric that we can compute between subsets of those items. We get a hierarchy of clusters via the following greedy algorithm:</div><div><ol><li>Let each item be a cluster (with a single element)</li><li>Let $S$ be the set of all clusters</li><li>While $|S| > 1$:</li><ol><li>Find the closest pair of clusters $X, Y$ in $S$.</li><li>Define a new cluster $Z := X \cup Y$</li><li>Add $Z$ to $S$, remove $X$ and $Y$ from $S$</li></ol></ol><div>So the diagram above implies the following possible sequence of cluster unions (it may be slightly different):</div></div><div><ol><li>$\{b\} \cup \{c\}$</li><li>$\{d\} \cup \{e\}$</li><li>$\{d,e\} \cup \{f\}$</li><li>$\{b,c\} \cup \{d,e,f\}$</li><li>$\{a\} \cup \{b,c,d,e,f\}$</li></ol><div>There are a number of obvious optimizations, for example, one does not have to recompute all distances after each creation of a new cluster. Rather - only the distances that involve the new cluster.</div><div><br /></div><div><h3>What is It Good For?</h3></div><div>In most of the use cases that we employed, the initial atoms were triangular facets of a <a href="https://en.wikipedia.org/wiki/Polygon_mesh">3D mesh</a>. One such use case is mesh segmentation, that is the process of breaking down a 3D object into meaningful sub-parts. There's a <a href="http://pers.ge.imati.cnr.it/attene/PersonalPage/pdf/TVC06_preprint.pdf">well-known paper from 2006 by Attene et al</a> that describes such an approach. The metric chosen for distance between segments(=clusters) is how much they resemble certain primitive shapes the authors chose in advance (cylinder, cube, sphere, etc.).</div><div>As can be seen in this image taken from the paper, once one has the full hierarchy of segments, this tree can be trimmed according to the number of clusters one wishes.</div></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-Na7JNqtFOPk/WosUgly_9mI/AAAAAAAARxw/WZ6yd2Pd-hAo5majFsEC2M2ew5RlzFc7ACLcBGAs/s1600/hs_levels.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="510" data-original-width="824" height="198" src="https://1.bp.blogspot.com/-Na7JNqtFOPk/WosUgly_9mI/AAAAAAAARxw/WZ6yd2Pd-hAo5majFsEC2M2ew5RlzFc7ACLcBGAs/s320/hs_levels.PNG" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">source: "Hierarchical mesh segmentation based on fitting primitives" by Attene et al<br /><br /></td></tr></tbody></table><h3>The Problem With HC</h3><div>The natural approach we took was to consider this not as atoms where all pairwise distances needed to be considered, but as a graph, where only distances between neighboring vertices had to be considered. In the 3D mesh case - adjacent faces were represented by neighboring atoms in the HC tree. So now we simply put all the edges of the graph (and the respective distances) into a some implementation of a min-heap, and began the simple process of:</div><div><ul><li>Extracting the minimal edge</li><li>Uniting the clusters it connected</li><li>Updating the graph (and the edges in the heap) accordingly</li></ul><div>This became an issue when the number of items stored in the heap was in the millions and tens of millions, which is very much the case when you get a high-quality 3D-scan of a room, for example. It turned out that operations on the heap became unbearably expensive, and the memory footprint was terrible, since we had to store this huge heap in the RAM.</div></div><div><br /></div><h3>The Solution: HHC</h3><div>We realized that changes in the HC tree were almost always very local - one computes the distance between pairs of clusters, which are neighboring nodes in the graph, and sometimes unites them in a way which affects only the neighbors of the united clusters. So why not divide and conquer?</div><div>What we ended up doing is this:</div><div><ul><li>Break down the model very crudely into K parts, by doing something that is not far from just putting it on a grid and taking cubes. Choose K such that each part will have not so many facets in it, but not too little.</li><li>Run HC on each part separately until the number of clusters in the part becomes small.</li><li>Now unite adjacent parts until the number of clusters in each part is again not too big but not too small.</li></ul><div>Note that this is in effect doing a Hierarchical Clustering of the parts, hence the winning name.</div></div><div>Also note that it effectively means you work on a number of very small heaps all the time and never on a very large one. This means heap operations are now considerably cheaper, and indeed the memory footprint went down by a factor of 5 or so, and the running time was improved dramatically, on machines with slower hard drives (since less swapping was involved).</div><div><br /></div><h3>The Price: Accuracy</h3><div>As it often happens, the price of heuristics is that they mess up the algorithm's accuracy. In our case - it means that if the minimal edge happens to connect atoms that lie in different parts - you will get to it much later than you otherwise would have, but the reduction in running time and resource consumption made it worth our while.</div><div><br /></div>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-21291249575078406202017-12-07T10:09:00.000+02:002017-12-07T10:11:51.602+02:00Fun at Work: What to Do When a Colleague Tells a Silly JokeSo, your colleague told a bad joke, and the only proper response is a rim shot sound. However, you have no drum kit within reach, so what you really need is a keyboard shortcut, shall we say Ctrl+Alt+Shift+R to play the following rim shot sound effect.<br /><div><br /></div><br /><audio controls=""> <source src="https://ia800501.us.archive.org/17/items/rimshot_739/rimshot.mp3" type="audio/mpeg"></source>Your browser does not support the audio element. </audio><br /><h4><br /><br />So, here's how you do it in Ubuntu:</h4><br /><ol><li>Download the above effect. Suppose you saved it to ~/rimshot.mp3</li><li>Install some shell tool that plays audio files. I use <i>play</i> from the <i>sox</i> package.<br /><pre style="background-color: #eff0f1; border: 0px; color: #111111; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 13px; font-stretch: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1em; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"><code style="border: 0px; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;">sudo apt-get install sox<br />sudo apt-get install sox libsox-fmt-all</code></pre></li><li>Go to System Settings -> Keyboard -> Shortcuts -> Custom Shortcuts</li><li>Click on the '+' sign to add a new one:<br /> <div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-x9r8tFTZNU8/Wij0abItEfI/AAAAAAAAPes/uIAZvQQ2pQMdr8FrfMSMKUbIoZIT7DpsQCLcBGAs/s1600/Selection_549.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="216" data-original-width="250" height="172" src="https://1.bp.blogspot.com/-x9r8tFTZNU8/Wij0abItEfI/AAAAAAAAPes/uIAZvQQ2pQMdr8FrfMSMKUbIoZIT7DpsQCLcBGAs/s200/Selection_549.png" width="200" /></a></div></li><li><div class="separator" style="clear: both; text-align: left;">Pick a name and have it run the command 'play' on your file:</div><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-S79vUIg1JFQ/Wij1raz6LDI/AAAAAAAAPe8/cQsVErarpSgXS_6CV_0GaxpZpuO2D3fFQCLcBGAs/s1600/Selection_551.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="195" data-original-width="316" src="https://3.bp.blogspot.com/-S79vUIg1JFQ/Wij1raz6LDI/AAAAAAAAPe8/cQsVErarpSgXS_6CV_0GaxpZpuO2D3fFQCLcBGAs/s1600/Selection_551.png" /></a></div><div class="separator" style="clear: both; text-align: center;"></div></li><li><div class="" style="clear: both; text-align: left;">Click on the word "Disabled at the end of the line of your newly created shortcut, press the key combination you like (e.g. Ctrl+Alt+Shift+R), and your done.</div></li><li><div class="" style="clear: both; text-align: left;">Wait for a colleague to tell a silly joke.</div></li><li><div class="" style="clear: both; text-align: left;">Hit Ctrl+Alt+Shift+R.</div></li><li><div class="" style="clear: both; text-align: left;">Go out on a hight note.</div></li></ol><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/1Lkikhfdnew/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/1Lkikhfdnew?feature=player_embedded" width="320"></iframe></div><br /></div><div><br /></div><div><br /></div><div><br /></div>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-76362405911017781842017-11-23T22:17:00.000+02:002017-11-24T21:36:35.794+02:00How to Utilize Computing Power That is Now "Wasted" in BlockchainAs of the time I'm writing this, the Bitcoin network consumes more electricity than 159 of the countries in the world, as pointed out <a href="https://twitter.com/noamr/status/933661809382428677">here</a>.<br /><div style="text-align: center;"><img height="204" src="https://pbs.twimg.com/media/DPUIJ_nW4AElZXd.jpg:large" width="400" /></div>To be clear - all this electricity is wasted by computers trying to solve (via brute-force) some computational problem. The first computer to solve it - is rewarded by the network, transactions are validated, another block is created, and everyone move on to the next problem. Another day on the blockchain.<br /><br />And here's the somewhat weird part - nobody cares about the problems or the solutions. The only reason they are of interest, is that we can estimate the difficulty of solving them. <span style="background-color: yellow;">So a huge amount of energy and resources is wasted on solving problems no one cares about</span>.<br /><br /><h3><b><br /></b></h3><h3><b>Why Not Solve Important Problems Instead ?</b></h3>I was thinking about this a few weeks ago when I thought - what if, instead of all this waste, those computers tried to solve hard problems that people <b>do</b> care about?<br />The famous class of <a href="https://en.wikipedia.org/wiki/NP_(complexity)">NP-complete</a> problems has a few problems in it that are real-world problems (other complexity classes make sense too, of course), for example - the traveling salesman problem (aka <a href="https://en.wikipedia.org/wiki/Travelling_salesman_problem">TSP</a>). What if people who had TSP instances, because they are trying to navigate somewhere, or choose a route for some robot running erands in a large warehouse, could submit them to the blockchain and have them solved for them, using all this computing power?<br />There is an abundance of hard real-world computational problems, many of which arise in Chemistry and Biology. I understand very little about it, but I know researchers who actually send data to be processed for several days on a super-computer, just to get results for their research.<br />What if an entire blockchain network was, in effect, a crowd-sourcing project to solve hard computational problems? Wouldn't it be nice to put all this computing power to good use? Changing the existing Bitcoin protocol is probably out of the question at this point, but maybe a new crypto-coin, dedicated for that purpose? Maybe a different crypto-coin for different types of computational problems, the options are many, and seem interesting, at least in theory.<br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><img alt="תוצאת תמונה עבור computation stock photo" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTQntHhaz7EFELNjraBB-85Aikkd3XNnprKnoNklkuGip9bUc4MzA" style="margin-left: auto; margin-right: auto;" /></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-size: xx-small;">An illustration Google image search came up with for "hard computation"</span></td></tr></tbody></table><h3></h3><h3>The Nice Thing About This Idea</h3>There are a few appealing notions here:<br /><br /><ol><li>Hard problems are already sorted into complexity classes. This means that hard problems of the same class are convertible to one another. We can decide that the network actually solves <a href="https://en.wikipedia.org/wiki/Boolean_satisfiability_problem#3-satisfiability">3SAT</a> instances, and reduce any TSP instance to a 3SAT, and then submit it to the network.</li><li>It means hard problems actually have economic value <b>for their hardness</b>, where in the past it was only a <b>cost</b> associated with solving it. Now - solving the problem will oddly be its own reward... which is kind of neat.</li><li>Maybe when submitting a problem, one can offer a reward for solving it.</li></ol><br /><h3>Some of The Problems</h3><div>While being a nice idea, it has tons and tons of problems. Here are just a few</div><div><ol><li>One can game the system - submit a problem, already knowing its solution, and collect the reward by solving it. This one is probably not hard to mitigate by scrambling the problem while converting it to the format readable by the network.</li><li>A harder issue is how do we know an instance is hard at all to begin with? There are SAT solvers in the world exactly because there are many heuristics that cover some types of instances of the problem.</li><li>Do people really need exact solvers? At least for the case of NP problems - for many of them an approximated solution is good enough, so is this really filling a need that people actually have? I don't know.</li></ol><div><br /></div></div><div>There are probably many other issues with this idea, but I thought it would be nice to put it out there.</div><div><br /></div><div><br /></div><div><br /></div><div><h3>P.S.</h3></div><div>The world is a big place, I will be very surprised if I'm the first to come up with this...</div>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-11079691894561803282017-04-26T00:16:00.001+03:002017-04-26T00:16:21.981+03:00Solving the Wrong Problem: My Take on 3DOR 2017<span style="font-family: Arial, Helvetica, sans-serif;">This week I attended the 10th <a href="http://liris.cnrs.fr/eg3dor2017/">3D Object Recognition</a> workshop, which was held as preliminary part of <a href="http://www.eurographics2017.fr/">EuroGraphics</a>. To</span><span style="font-family: Arial, Helvetica, sans-serif;"> sum up my impression from the vast majority of the works, I felt that <b>the academia is working on the wrong problems</b>.</span><br /><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif;">Specifically - much of the research presented (though not all) dealt with <a href="https://en.wikipedia.org/wiki/Computer-aided_design">CAD</a> models, indexing them, analyzing them, finding similarities, descriptors, and transformations for them. This is, in my opinion, an approach that has lost touch with the actual state of data in the real world, and is driven mostly by cultural reasons such as the existence of previous work to rely on and CAD-based benchmarks to run. </span><br /><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/-ywjSLYkbS6s/WP-6f-NaiQI/AAAAAAAAHrk/QLL-R_1WaGwvIsTYhvMeD1guImzTS38SQCLcB/s1600/scanned_vs_cad.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="185" src="https://3.bp.blogspot.com/-ywjSLYkbS6s/WP-6f-NaiQI/AAAAAAAAHrk/QLL-R_1WaGwvIsTYhvMeD1guImzTS38SQCLcB/s320/scanned_vs_cad.png" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Scanned and CAD chair (not the same chair, of course)</td></tr></tbody></table><br /><span style="font-family: Arial, Helvetica, sans-serif;">In the past two years, we have seen an <b>increasing number of 3D scanners and depth cameras</b>, ranging from low quality devices - costing just a few hundreds of dollars - to expensive, high resolution, industrial devices, that produce impressive results. The tables have turned, and scanned data, which was a small minority, can now be easily generated in large quantities. This data ranges from <a href="https://www.cs.york.ac.uk/cvpr/pronto/">lab-scanned toys</a>, to huge urban scenes scanned by drones, nevertheless, the majority of the algorithmic works presented in 3DOR dealt with CAD models. I believe that there are two main reasons for that:</span><br /><br /><ol><li><span style="font-family: Arial, Helvetica, sans-serif;">There are <b>almost no tagged scanned data sets</b>, and none of substantial size (<a href="http://people.sutd.edu.sg/~saikit/projects/sceneNN/">SceneNN</a>, perhaps the best work so far, has only 100 scenes).</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;"> Most existing methods are <b>tailored to CAD</b> models, and are thus sensitive to one or all of the following traits, common in scanned data:</span></li><ol><li><span style="font-family: Arial, Helvetica, sans-serif;">High-frequency noise due to scanner accuracy issues.</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">Incomplete models due to occlusion or simply unscanned sides of the object.</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">Holes.</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">Open boundaries.</span></li></ol></ol><div><span style="font-family: Arial, Helvetica, sans-serif;">Reason (1) becomes even more of an issue to anyone wishing to follow the deep learning trend, as it - as most ML approaches - requires tagged data sets of considerable size. </span></div><div><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-nrSWcTyEvUs/WP-7cwEvn1I/AAAAAAAAHrs/GBruAQoQ2FgdiiFOSDxBffVcbyrXjVTXQCLcB/s1600/049_segmented.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="240" src="https://1.bp.blogspot.com/-nrSWcTyEvUs/WP-7cwEvn1I/AAAAAAAAHrs/GBruAQoQ2FgdiiFOSDxBffVcbyrXjVTXQCLcB/s320/049_segmented.png" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">A scanned scene from SceneNN data set</td></tr></tbody></table><div><br /></div><div><span style="font-family: Arial, Helvetica, sans-serif;">I believe that there are two types of data the academia should address seriously in the upcoming year or two - scanned small scale data, such as singular models and indoor scenes, and scanned large scale data, such as entire buildings, and streets. With the <a href="https://9to5mac.com/2017/02/21/kgi-oled-iphone-8-to-feature-revolutionary-3d-sensing-front-camera-detect-depth-for-games-and-facial-recognition/">upcoming depth camera in iPhone8</a>, we can expect a proliferation of the former, while the latter will be the result of increasing use of industrial scanners in security, construction, and drones.</span></div><div><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div><div><span style="font-family: Arial, Helvetica, sans-serif;">In my experience, algorithms that worked well with CAD models, more often than not prove to be useless for scanned data. This is bad news for reusing much of previous work as-is, but is also good news, as it brings hope that we'll see exciting new approaches to 3D retrieval and recognition in upcoming years, that will truly have an effect on technology being developed, and thus on people's lives.</span></div><br /><br />Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com2tag:blogger.com,1999:blog-642244788469558745.post-55702633417450953592017-03-28T22:51:00.000+03:002017-03-28T22:51:07.218+03:00The UX of Work Emails<span style="font-family: Arial, Helvetica, sans-serif;">The polite way to get a co-worker's attention to discuss an issue without bothering someone, is to send an email or some other form of asynchronous communication.</span><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://img.memesuper.com/9a947f55ff60dae6bd7b0c97978469ab_and-now-we-wait-now-we-wait-memes_180-159.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" src="https://img.memesuper.com/9a947f55ff60dae6bd7b0c97978469ab_and-now-we-wait-now-we-wait-memes_180-159.jpeg" /></span></a></div><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif;">In recent years I have found that it is very useful to think, when writing an email, <b>more like a UX designer than a writer</b>. This is because an email is meant to induce behavior, specifically, in addition to getting my message across, I want a quick response.</span><br /><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: large;">So when composing an email I...</span><br /><ol><li><span style="font-family: Arial, Helvetica, sans-serif;"><b>Use bullet points:</b> they make replying to different points in the email much easier, and requires less explaining when doing so.</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;"><b>Highlight important stuff</b>, and in general, make scheming through it easy and informative. </span></li><li><span style="font-family: Arial, Helvetica, sans-serif;"><b>Use images when I can</b>, because people love images and respond to them more than to text (as any Facebook page manager will tell you). This is not to say I start digging through image banks, rather - I use plenty of screenshots all the time (I use <a href="http://shutter-project.org/">Shutter</a> on Ubuntu and the <a href="https://support.microsoft.com/en-us/help/13776/windows-use-snipping-tool-to-capture-screenshots">Windows Snipping Tool</a> on Win7). And yes, the occasional meme, if I have a big block of text with no relevant image to accompany it.</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">For a long email - <b>start it with a tl;dr version</b> of it, summarizing the whole thing in a sentence or two. This works in a similar way to a news story's headline - it gives the appropriate framing and context.</span></li><li><b style="font-family: Arial, Helvetica, sans-serif;">Use the subject line to help recipients sort through their emails</b><span style="font-family: Arial, Helvetica, sans-serif;">. I believe that the subject line is usually ignored when actually reading an email. It is read when people sort through a long list of emails, or get a notification. It therefore should be short, and useful in reminding the reader how this email differs from others on the list.</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;"><b>Use code that looks like code</b>. I use <a href="https://tohtml.com/colorer.php?type=cpp/">this website</a> to format the code parts of an email and make them look like code. It helps readability, and looks cool.<br /><pre style="background: rgb(255, 255, 255);"><span style="color: maroon; font-weight: bold;">int</span> RandomInt<span style="color: #808030;">(</span><span style="color: #808030;">)</span> <span style="color: purple;">{</span><br /> <span style="color: maroon; font-weight: bold;">return</span> <span style="color: #008c00;">4</span><span style="color: purple;">;</span><br /><span style="color: purple;">}</span></pre></span></li><li><span style="font-family: Arial, Helvetica, sans-serif;"><b>Make it cross-platform. </b>People read their emails on various devices, so I try to be very conservative with attachments, and limit them to PDFs and other easily-read formats, when possible. When I have some 3D model in a proprietary format that illustrates my point - I may send it, but I send an image of it as well, so that colleagues can make sense of it even if they are on the train, using their phone to read emails.</span></li></ol><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://www.mememaker.net/static/images/memes/4393744.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="239" src="https://www.mememaker.net/static/images/memes/4393744.jpg" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">An image. Yeah, I know, amazing.</td></tr></tbody></table><br /><div><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-74885750718022218152017-01-31T10:29:00.000+02:002017-03-28T17:41:31.006+03:00Generate a Puzzle for Your Math Class in 5 Minutes<div class="separator" style="clear: both; text-align: center;"><a href="http://s3.amazonaws.com/tpt-uploads-production/uploads/Untitled-223.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="color: black; font-family: "arial" , "helvetica" , sans-serif;"><img border="0" src="http://s3.amazonaws.com/tpt-uploads-production/uploads/Untitled-223.jpg" height="86" width="320" /></span></a></div><br /><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: inherit;">There's a famous puzzle, often referred to as the <a href="https://en.wikipedia.org/wiki/Zebra_Puzzle">Zebra Puzzle</a>. It goes something like this:</span></span><br /><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span><br /><ol><li><span style="font-family: "arial" , "helvetica" , sans-serif;">There are five houses.</span></li><li><span style="font-family: "arial" , "helvetica" , sans-serif;">The Englishman lives in the red house.</span></li><li><span style="font-family: "arial" , "helvetica" , sans-serif;">The Spaniard owns the dog.</span></li><li><span style="font-family: "arial" , "helvetica" , sans-serif;">...</span></li><li><span style="font-family: "arial" , "helvetica" , sans-serif;">...<br />...</span></li></ol><span style="font-family: "arial" , "helvetica" , sans-serif;">Here follow many more facts detailing who lives next to whom, and which pets they own and so on, until the final question is given: <b>Who owns the zebra?</b></span><br /><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: inherit;"></span></span><span style="font-family: "arial" , "helvetica" , sans-serif;">There is no quick and clean solution for this puzzle that involves a single big "Aha!" moment, but rather a series of steps, making ad-hoc assumptions, and trying to see if they sit well with each other and with the facts given, until a solution is found.</span><br /><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span><br /><h3><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: large;">Constraint Satisfaction Problems</span></h3><div><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif;">This puzzle belongs to a class of problems called </span><a href="https://en.wikipedia.org/wiki/Constraint_satisfaction_problem" style="font-family: arial, helvetica, sans-serif;">Constraint Satisfaction Problems</a><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif;">, or CSP. </span></div><div><span style="color: #252525; font-family: inherit;"><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif;">While CSPs in general are hard to solve, even for computers, small instances of them are both easy to create, and make for popular puzzles. An example of such puzzle is <a href="https://en.wikipedia.org/wiki/Sudoku">Sudoku</a>.</span></span></div><div><br /></div><h3><span style="color: #252525; font-family: inherit; font-size: x-small;"><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif; font-size: large;">Floors Puzzles</span></span></h3><div><span style="background-color: white; color: #252525; font-family: "arial" , "helvetica" , sans-serif;">Here's a really easy CSP I just came up with:</span></div><div><ol><li><span style="color: #252525; font-family: inherit;"><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif;">There are 4 floors in the building.</span></span></li><li><span style="color: #252525; font-family: inherit;"><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif;">The rooster does not live on the top floor.</span></span></li><li><span style="color: #252525; font-family: inherit;"><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif;">The cat lives two floors under the lion.</span></span></li><li><span style="color: #252525; font-family: inherit;"><span style="background-color: white; font-family: "arial" , "helvetica" , sans-serif;">the dog lives in a lower floor than the rooster.</span></span></li></ol><div><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div><div><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif; font-size: large;"><b>Which animal lives on which floor?</b></span><br /><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;">Spoiler alert: if you like to solve this puzzle, do so now, since the next section will reveal the solution. The puzzle is, by the way, so easy that I suggest you solve it yourself anyway, just to get an understanding of what it feels like.</span></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://previews.123rf.com/images/sarahjanet/sarahjanet1111/sarahjanet111100018/11463867-Colourful-rooster-American-Brown-Leghorn-rooster-on-white-background-Stock-Photo.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><span style="color: black; font-family: "arial" , "helvetica" , sans-serif;"><img border="0" src="http://previews.123rf.com/images/sarahjanet/sarahjanet1111/sarahjanet111100018/11463867-Colourful-rooster-American-Brown-Leghorn-rooster-on-white-background-Stock-Photo.jpg" height="200" width="198" /></span></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: small;">An animal that does not live on the top floor</span></td></tr></tbody></table><div><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div><div><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;">This is a nice puzzle for 10 year old students. A similar puzzle with 3 floors will be suitable for 7 year olds, and naturally, more floors can make it increasingly harder to solve.</span></div></div><div><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div><div><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div><h3><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif; font-size: large;">Create Your Own Floors Puzzle in 5 Minutes</span></h3><div><ul><li><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;">Choose animals and number of floors. </span></li></ul><ul><li><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;">Draw a diagram of which animal goes where, e.g.:</span></li></ul><ul><li><span style="font-family: "arial" , "helvetica" , sans-serif;">Write down rules that describe your building - e.g. "the dog lives 3 floors below the lion".</span></li></ul><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-Zkly2IL0elU/WJBIMZLUbbI/AAAAAAAADGs/8DjaMfki6GYuRxrEQKRPHW36mMytTgEFACLcB/s1600/4floors.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="color: black; font-family: "arial" , "helvetica" , sans-serif;"><img border="0" height="200" src="https://2.bp.blogspot.com/-Zkly2IL0elU/WJBIMZLUbbI/AAAAAAAADGs/8DjaMfki6GYuRxrEQKRPHW36mMytTgEFACLcB/s200/4floors.jpg" width="150" /></span></a></div><div class="separator" style="clear: both; text-align: left;"></div><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span><br /><div><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div><div><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;">Over a certain number - some of the rules will be redundant, that is - the puzzle may be solved even if those rules are not given, but don't worry about that. As a rule of thumb - the number of rules should be slightly smaller than the number of floors.</span></div></div><div><br /></div><h3><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif; font-size: large;">Checking Solutions</span></h3><div><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;">Note that it may be the case that there will be correct solutions that are not identical to the one you used to write the puzzle, but that's okay, because the puzzle is about finding a solution, not the solution. While it is possible, in principle, to check whether the rules you chose have more than one solution, it will probably take more than the 5 minutes promised in the title of this post... </span><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;"></span><br /><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;"><br /></span><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;">So there you have it - generate a puzzle for your math class in five minutes or less. Enjoy.</span><br /><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="color: #252525; font-family: inherit;"><br /></span><span style="color: #252525; font-family: inherit;"><br /></span><span style="color: #252525; font-family: inherit;"><br /></span><span style="color: #252525; font-family: inherit; font-size: large;"><b>P.S.</b></span></span><br /><span style="color: #252525; font-family: "arial" , "helvetica" , sans-serif;">On a less-practical note, about a year ago I wrote a post tying <a href="http://www.shirpeled.com/2016/01/np-complete-problems-as-online-math.html">"good" puzzles to NP-complete problems</a>, and this current post is really just another example of that.</span></div>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-34828382628891561822016-10-05T11:16:00.003+03:002016-10-07T22:09:39.684+03:00Notes from my "Intro to Information Theory" time<br />For two years, starting October 2010, I was a teaching assistant in the Introduction to Information Theory course at the Hebrew University, which was taught by <a href="http://www.cs.huji.ac.il/~werman/">Prof. Michael Werman</a>, and the following year by <a href="http://www.cs.huji.ac.il/~benor/">Prof. Michael Ben-Or</a>.<br />During that time, I a weekly two-hour tutorial, which was sometimes an extension of what was discussed in the lecture, and sometimes (as in the case of error correction codes) simply dealt with other topics.<br /><br />After writing <a href="http://www.shirpeled.com/2016/09/check-digit-poor-mans-error-correction.html">the previous post on check digits</a>, I dug up the old notes, and found them to be quite helpful in refreshing my memory on the matter.<br /><br />So, hoping it will prove helpful to others as well, and under an assumption that I'm not violating anyone's copyrights, here they are:<br /><br /><iframe height="480" src="https://drive.google.com/file/d/0B5rBtG_Lw_9lT2NIbFp6LVlyV28/preview" width="480"></iframe>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-46957606560171235132016-09-27T16:54:00.000+03:002016-09-27T16:56:15.795+03:00Check digit: the poor man's error correction code<h3>The Israeli ID number and the Luhn Algorithm</h3><div><br /></div>The Israeli ID number, assigned to every Israeli resident or citizen, has 9 digits: the left 8 digits are the actual number, whereas the right-most digit is a check digit.<br />The check-digit is computed using the <a href="https://en.wikipedia.org/wiki/Luhn_algorithm">Luhn algortihm</a> which is:<br />1. Multiply digits in even places by 2.<br />2. Add the digits in the odd places (not including the check-digit itself) to the sum of digits of numbers you got in (1).<br />3. Set the 9th digit to be the number required to complete the sum from (2) to the next multiple of 10.<br /><br /><h4>For example</h4><div><br /></div>The number 99035612 will be processed as follows:<br />9 - odd place, leave as is -> 9<br />9 - even place, multiply by 2 and take sum of digits -> 18 -> 9<br />0 - odd place, leave as is -> 0<br />3 - even place - multiply by 2 -> 6<br />5 - odd place, leave as is -> 5<br />6 - even place, multiply by 2 and take sum of digits -> 12 -> 3<br />1 - odd place, leave as is -> 1<br />2 - even place, multiply by 2 -> 4<br /><br />sum all the above to obtain 37, which requires adding 3 to complete it to the nearest multiple of 10, thus 3 is chosen to be the check digit.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-3y-WSpik_hQ/V96YWKZ0WsI/AAAAAAAADCk/7pVXq0niRW8FmA1WmKBW8UdkNQMLY4WugCLcB/s1600/smart%2Bid.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="197" src="https://1.bp.blogspot.com/-3y-WSpik_hQ/V96YWKZ0WsI/AAAAAAAADCk/7pVXq0niRW8FmA1WmKBW8UdkNQMLY4WugCLcB/s320/smart%2Bid.jpg" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Had this been a valid ID, the check digit would have been 2 (not 9)<br />(image source: nbn.org.il)</td></tr></tbody></table><br /><h4></h4><h4>Why all the fuss?</h4><div><br /></div>The most obvious idea for a check digit would be sum of digits modulo 10, so why all this odd-even business? It turns out it is intended to catch the very common transcription mistake of transposing two adjacent digits, and by the by also catches most of the cases of twin digits mistakes (i.e. aa->bb). In addition, it is simple, and therefore realistically usable for clerks in the pre-computers age.<br /><br /><br /><h3></h3><h3></h3><h3>The Luhn Algorithm's "unfixable" fault</h3><br />Interestingly, the Luhn algorithm cannot detect all transpositions of two adjacent digits. Specifically, the sequences 09 and 90 both contribute 9 to the sum computed in step (2) so this transposition will not cause a change in the check digit and will not be detected.<br />So I grabbed a piece of paper and tried to come up with a similar algorithm that will catch *all* transpositions, only to find out that - if we restrict ourselves to similar algorithms (wanting to preserve the simplicity of the computation) - there is no such solution.<br />To be precise, let $f:\{0,...,9\}\rightarrow\{0,...,9\}$ be a permutaion, then there exist $a \neq b \in \{0,...,9\}$ such that $f(a) + b \equiv a + f(b) (\textrm{mod} 10)$.<br />My friend, Lior Yanovski, suggested an elegant proof for this:<br />Assume, by way of negation, that $a\neq b \Rightarrow f(a) + b \not\equiv a + f(b) (\textrm{mod} 10)$.<br />It follows that $ f(a) - a \not\equiv f(b) - b (\textrm{mod} 10)$, which means the function $g(x) := f(x) - x (\textrm{mod} 10)$ is a permutation.<br />If we sum $g(x)$ over $x$ we obtain $\sum_x f(x) - \sum_x x \equiv 0 (\textrm{mod} 10)$ simply because both $f$ and the identity are permutaions adding up to 55. On the other hand, if $g$ is indeed a permutation - summing up its values would give $5 (\textrm{mod} 10)$, i.e., a contradiction!<br />So if we were to look for a function to replace the "multiply by 2 and take sum of digits" from the Luhn algorithm, while maintaining the rest of the algorithm's structure, and covering all adjacent digits transpositions - we won't find one.<br /><br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://2.bp.blogspot.com/-t0yS_GDmjJU/V96bBjfnScI/AAAAAAAADC0/xa8dnd3k-p8tD8n5WzNWw8OCM7gTEldqQCLcB/s1600/Hans_Luhn.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="200" src="https://2.bp.blogspot.com/-t0yS_GDmjJU/V96bBjfnScI/AAAAAAAADC0/xa8dnd3k-p8tD8n5WzNWw8OCM7gTEldqQCLcB/s200/Hans_Luhn.png" width="168" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Hans Peter Luhn 1896-1964<br />(Image source: asist.org)</td></tr></tbody></table><h3></h3><h3></h3><h3><br /></h3><h3>Fix #0: Find only transpositions</h3><div><br />We could multiply every digit by its place, and take this sum modulo 10, i.e. define the check digit to be $\sum_{i=1} ^n i \cdot a_i (\textrm{mod} 10)$. This will detect all adjacent transpositions, but it will do a very poor job in detecting single digit errors. Seeing how 10 shares divisors with most of the numbers in $0,...,9$, multiplying by either of them and taking the remainder modulo 10 discards some information. For example $5\cdot x$ will always be either 0 or 5 (assuming $x$ is an integer). This means that a random error in the fifth digit will cause a change in the check digit only 50% of the times, and somewhat similar problems arise with digits in even places.<br /><br /></div><h3>Fix #1: Abandon base 10</h3><br />A closer inspection would reveal that the proof of the Luhn algorithm's fault relies heavily on the fact that 10 is an even number, since the expression $\sum_{i=1} ^n i (\textrm{mod} n)$ is $\frac n 2$ for even values of $n$ but $0$ for odd values of $n$. If we had used an odd base for this entire computation - things would be different, but perhaps less intuitive to compute by hand.<br />Indeed, some check digit systems, such as the one used in ISBN 10 (for bank transfers) employ a similar trick with 11 as the base of the modular operations.<br /><h3></h3><h3></h3><h3><br /></h3><h3>Fix #2: Abandon simplicity</h3><br />If we allow yet more complex computations, then there are some algorithms that produce a check digit that will detect all single-digit errors as well as all transpositions of adjacent digits. The oldest one probably being <a href="https://en.wikipedia.org/wiki/Verhoeff_algorithm">Verhoeff algorithm</a>, from 1967. Verhoeff, who is now retired and an avid creator of math-inspired sculptures, took an empirical approach, by analyzing data from the Dutch postal service, classifying and counting common errors. He followed to create a code that not only detects all adjacent digits transpositions and single digit errors, but also detects errors based on phonetic similarities in dutch, such as confusing 15 (vijftien) with 50 (vijftig).<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-9CCo5J_qOK0/V9-PwOTF3WI/AAAAAAAADDE/N1HCP0NqBtofZ25upe79GbYkmGnB92tHQCLcB/s1600/Verhoeff.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://1.bp.blogspot.com/-9CCo5J_qOK0/V9-PwOTF3WI/AAAAAAAADDE/N1HCP0NqBtofZ25upe79GbYkmGnB92tHQCLcB/s320/Verhoeff.jpg" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Jacobus Verhoeff, with his sculptures<br />(Image source: groene.nl)</td></tr></tbody></table>More recently (2004), <a href="https://en.wikipedia.org/wiki/Damm_algorithm">H. Michael Damm proposed an algorithm</a> that is slightly less complicated (but only very slightly), and has similar qualities.<br /><br /><br /><br /><h2></h2><h2>Some tests</h2><div><br />Running some quick scripts in python, I wanted to find out how well the <b>Luhn</b> algorithm, the <b>Damm</b> algorithm (I skipped implementing Verhoeff's) and the algorithm proposed in <b>Fix #0</b> above fare. I also added two more algorithms for fun:<br /><br /></div><div><ul><li><b>Naive</b> - $|\sum_{i = 1} ^{n - 1} (a_i - a_{i+1})| (\textrm{mod} 10)$.</li><li><b>RandomTable</b> - the Damm algorithm is based on using a table of a quasi group of order 10. So I wondered how well a random table would do, so I took 10 random permutations, one above the other, and used it in the same way the Damm algorithm is implemented.</li></ul><div><br />The errors introduced were:<br /><br /></div></div><div><ul><li>Adjacent transposition: 12345 -> 12435</li><li>One-over transposition: 12345 -> 14325</li><li>Random 2-digit transposition: 12345 -> 42315</li><li>Single digit random error: 12345 -> 19345</li><li>Two-digit random errors: 12345 -> 22346</li><li>3, 4, 5... 9 random errors.</li></ul><div><br />The table shows the miss rate. Note that 10% miss rate is the magic number that they all converge to, given enough noise. This is because if we were to choose some random function $f:(0...9)^n\rightarrow\{0...9\}$ then for two random inputs $x \neq y \in (0...9)^n$, clearly $Pr(f(x) \neq f(y)) = 0.9$. A random function on random data has a 10% miss rate, so useful algorithms try to get significantly better than 10% for specific cases, without causing spikes in the miss rate for other errors.<br /><br /></div></div><div><br /></div><style type="text/css">.tg {border-collapse:collapse;border-spacing:0;border-color:#999;} .tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#999;color:#444;background-color:#F7FDFA;} .tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#999;color:#fff;background-color:#26ADE4;} .tg .tg-qw6t{font-size:14px;font-family:"Comic Sans MS", cursive, sans-serif !important;;vertical-align:top} .tg .tg-yw4l{vertical-align:top} .tg .tg-9hbo{font-weight:bold;vertical-align:top} </style> <br /><table class="tg"> <tbody><tr> <th class="tg-qw6t">error \ algo</th> <th class="tg-yw4l">Luhn</th> <th class="tg-yw4l">Damm</th> <th class="tg-yw4l">Fix #0</th> <th class="tg-yw4l">Naive</th> <th class="tg-yw4l">Random</th> </tr><tr> <td class="tg-9hbo">Adjacent transposition</td> <td class="tg-yw4l">2%</td> <td class="tg-9hbo">0%</td> <td class="tg-9hbo">0%</td> <td class="tg-yw4l">70%</td> <td class="tg-yw4l">34%</td> </tr><tr> <td class="tg-9hbo">One-over transposition</td> <td class="tg-yw4l">87%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">9%</td> <td class="tg-yw4l">63%</td> <td class="tg-yw4l">22%</td> </tr><tr> <td class="tg-9hbo">Random transposition</td> <td class="tg-yw4l">45%</td> <td class="tg-yw4l">8%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">53%</td> <td class="tg-yw4l">27%</td> </tr><tr> <td class="tg-9hbo">1-digit error</td> <td class="tg-9hbo">0%</td> <td class="tg-9hbo">0%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">67%</td> <td class="tg-yw4l">36%</td> </tr><tr> <td class="tg-9hbo">2-digit error</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">44%</td> <td class="tg-yw4l">25%</td> </tr><tr> <td class="tg-9hbo">3-digit error</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">27%</td> <td class="tg-yw4l">18%</td> </tr><tr> <td class="tg-9hbo">4-digit error</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">17%</td> <td class="tg-yw4l">14%</td> </tr><tr> <td class="tg-9hbo">5-digit error</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">12%</td> <td class="tg-yw4l">11%</td> </tr><tr> <td class="tg-9hbo">6-digit error</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">11%</td> </tr><tr> <td class="tg-9hbo">7-digit error</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> </tr><tr> <td class="tg-9hbo">8-digit error</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> </tr><tr> <td class="tg-9hbo">9-digit error</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> <td class="tg-yw4l">10%</td> </tr></tbody></table><br /><div><br /></div><h2></h2><h2><br /></h2><h2>Error correction codes for edit distance?</h2><div><br />So, while this is a pre-computing-age problem, that is <a href="https://www.youtube.com/watch?v=luef1H24hU8">nowadays</a> a toy problem, it highlights an interesting issue: the standard error-correction codes treat a very specific domain, where errors are modeled as noisy coordinates in a vector, and so the notion of distance is just the <a href="https://en.wikipedia.org/wiki/Hamming_distance">Hamming distance</a>. Are there good codes for domains where the distance is more complicated, such as <a href="https://en.wikipedia.org/wiki/Levenshtein_distance">Levenshtein distance</a>?</div><div><br /></div><div><br />It turns out that once we tweak the noise model, we quickly step into the realm of open problems. While for the <a href="https://en.wikipedia.org/wiki/Binary_erasure_channel">Binary Erasure Channel</a>, which models noise as flipping bits, we've known the capacity ever since it was introduced, for the <a href="https://en.wikipedia.org/wiki/Deletion_channel">Deletion Channel</a>, which models noise as removing a bit from the input string, the capacity is still an open problem.</div><div>To summarize - edit distance correction codes are an interesting idea, but I doubt we'll see any progress in them soon, as even the fundamental questions of Information Theory turn out to be extremely challenging in this domain.</div><div><br /></div>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-50876951225348460062016-08-02T08:27:00.000+03:002016-08-02T08:28:41.259+03:00Pokémon GO meets FarmVille: a game pitchSo, here's a sketch for a mobile location-based farming simulation game I thought of:<br /><br /><h3>Elevator pitch:</h3><div><br /></div><b>Pokémon GO meets FarmVille</b>: players walk around in the real world, where real world locations have in-game roles. The players grow crops, and harvest them, and since this is the real world - they can 'own' land.<br /><br /><br /><h3>Basic principles:</h3><br /><ul><li><b>Each player can "own" portions of land</b> in the real world, and use it to grow crops.</li><li><b>Crops can be sold in markets,</b> which are also places in the real world (kind of like PokéStops).</li><li>Land can be bought and sold, workers can be hired, however, a player <b>must visit his/her land often</b> enough, otherwise <b>it becomes abandoned</b>, in which case other players can buy it cheaply.</li></ul>The latter is crucial to the game, as it plays to users habits (making it easy to buy and maintain land next to home / work, or on the way there), and prevents early adopters from hoarding land.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-nCmAg3aZZZw/V6AuXCQOy3I/AAAAAAAADBw/6FFI5S0JJ50WxhmYYS41rzBRwtgeboHTwCLcB/s1600/pokemongomeetsfarmville.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://3.bp.blogspot.com/-nCmAg3aZZZw/V6AuXCQOy3I/AAAAAAAADBw/6FFI5S0JJ50WxhmYYS41rzBRwtgeboHTwCLcB/s320/pokemongomeetsfarmville.png" width="266" /></a></div><br /><br /><h3>Gameplay:</h3><div><br /></div><h4>Buying land</h4>Each player starts the game with some in-game money, no workers, and some basic seeds (wheat, corn, or rice, depending on the climate).<br />Walking around in the real world, the player can see which pieces of land are available for buying, and for how much. Abandoned pieces of land are priced by their size, and the price of land owned by other users is determined by that user, who can also choose "not selling". Any player can bid for any piece of land they pass by, as long as they have the money. Selling land does not require the player to be present at the spot.<br /><br /><h4>Working the land</h4>Having bought a new piece of land, the player has to work the land and prepare it for seeding. If the player has hired workers - they can be left there to do the job, but otherwise - the player has to stand close to the land for a minute, tapping the screen of the mobile device, thereby "working the land".<br /><br /><h4>Crops </h4>Seeds for various crops can be bought at any market and planted in the land, requiring the player to visit the land in order to do so. Similarly to FarmVille, the crops take time to grow, and can rot if not harvested in time. Harvesting, like any type of work on the land, can be done by the player standing next to it and tapping the screen, or by workers left there for that purpose.<br /><br /><h4>Markets</h4>These are places in the real world, that play a part in the game but cannot be bought or sold and are determined by the system, similarly to PokéStops. Standing close to a market, a player can buy seeds, machinery, sell crops, and hire workers (for a predetermined time) with various levels of expertise.<br /><br /><h4>Weather and Location</h4>Crops can be grown only in places where the weather makes sense for it to happen, or in greenhouses, and real-world weather affects the virtual crops and their prices, so a storm may kill some of the crops, but raise prices.<br /><br /><h4>Advancement</h4>Players advance through levels through experience points that are gained by playing the game (growing crops, buying land, harvesting, hiring help, etc.).<br />Various achievements can be unlocked, such as managing 10 workers at once, growing exotic crops, owning a lot of land.<br /><br /><h4>Social aspect?</h4>Not sure, I haven't thought about it much, since I really don't like the way FarmVille did it...<br /><div><br /></div>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com1tag:blogger.com,1999:blog-642244788469558745.post-56953656573030587762016-07-10T08:26:00.000+03:002016-07-10T08:26:24.101+03:00My Perspective on Prisma: It's Burning Money FastFor the past couple of weeks - the photo-processing app Prisma has been gaining huge attention, and rightfully so - they use <a href="https://en.wikipedia.org/wiki/Convolutional_neural_network">CNNs</a> (+3 points for trendy buzz word) and AI (+2.5 points) to process its users' photos and turn them into truly impressive art work, inspired by great artists such as Van Gogh, Picasso, and others (+1.5 points for name dropping).<br /><br />Here's what it looks like on the famous Success Kid's image:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-6Yw9uzsSJwA/V4HVP2fBoNI/AAAAAAAADAw/NgyRXPLSP_YCRw3CsXei4fS0Km0zBtq_wCLcB/s1600/success_prisma1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://2.bp.blogspot.com/-6Yw9uzsSJwA/V4HVP2fBoNI/AAAAAAAADAw/NgyRXPLSP_YCRw3CsXei4fS0Km0zBtq_wCLcB/s320/success_prisma1.JPG" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div> Which is it pretty impressive. As usual with these things, well lit highly contrasted photos work best, and it's loads of fun to play with.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://3.bp.blogspot.com/-ZJpt9yr5jvI/V4HVRVVApOI/AAAAAAAADA0/uoJKp-G91yU3qFI6YV3bZpv3_1z6fw9nACLcB/s1600/success_prisma2.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://3.bp.blogspot.com/-ZJpt9yr5jvI/V4HVRVVApOI/AAAAAAAADA0/uoJKp-G91yU3qFI6YV3bZpv3_1z6fw9nACLcB/s320/success_prisma2.JPG" width="320" /></a></div><br />Since the app is free, it begs the question: <b>how do these people plan to make money?</b><br />Well, here are a few things to consider:<br /><br /><ol><li>Some of their filters are branded (e.g. by Palmolive), thus generating revenue through advertising.</li><li>Since yesterday, the photos come with a water mark on their bottom-right corner, which I guess won't be there in some premium paid version.</li><li>As a friend of mine pointed out: it is very hard to do these computations on the device, and as he found out - indeed when you put your device into airplane mode - the app doesn't work, so the heavy lifting must be done in the cloud. To quote my friend: "this is one free app with a huge AWS bill".</li><li>In its <a href="https://www.producthunt.com/tech/prisma-2">Product Hunt thread</a>, one of the Co-founders responded to an inquiry about their business model by promising that the app will always be free:</li></ol><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://4.bp.blogspot.com/-OOsHWuY74v4/V4HXZd0jp6I/AAAAAAAADBA/8NqUkzY61esTyOFwFNYZiv6augm3-V3LgCLcB/s1600/Selection_193.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="124" src="https://4.bp.blogspot.com/-OOsHWuY74v4/V4HXZd0jp6I/AAAAAAAADBA/8NqUkzY61esTyOFwFNYZiv6augm3-V3LgCLcB/s320/Selection_193.png" width="320" /></a></div><br /><h3>Conclusion: smells like trouble</h3>So while this company is obviously putting out a good product (especially if we ignore the annoying 2-3 seconds wait when applying a filter), I believe balancing their cloud bill with revenue from advertisers seems like a big challenge. Of course, they may be aiming at getting bought quickly by the big guys, but the model of allowing users to heavily drain cloud resources, with a limited ability to monetize (unlike search results, social networks feed, etc.), may mean they won't live long enough for this to happen.<br /><br /><br /><br />Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-89656023637209183332016-07-01T09:35:00.000+03:002016-07-01T21:45:24.208+03:00Deliberate Learning: 3 Tips for Acquiring New SkillsRecently, through <a href="http://freakonomics.com/podcast/peak/">Freakonomics</a>, I came across the notion of deliberate practice. The idea, originally introduced by <a href="http://projects.ict.usc.edu/itw/gel/EricssonDeliberatePracticePR93.PDF">Ericsson et al</a> in 1993, and more notably popularized by Malcolm Gladwell's <a href="http://gladwell.com/outliers/">"Outliers"</a>, is that the contribution of natural talent to greatness in art, science, and sports, is far smaller than we tend to assume.<br />The tl;dr version of it is: the thing that differentiates the greatest among us from the rest is not their talent, but the manner in which they practice. Specifically, they practice an awful lot, and do so in a <b>reflective process that efficiently translates the invested time to a consistent improvement in performance.</b><br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://upload.wikimedia.org/wikipedia/commons/1/1e/Wolfgang-amadeus-mozart_1.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="200" src="https://upload.wikimedia.org/wikipedia/commons/1/1e/Wolfgang-amadeus-mozart_1.jpg" width="135" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Mozart - a guy who was great at something</td></tr></tbody></table> While I don't expect to become the world's greatest anything, some principles of deliberate practice struck me as familiar, and made me think about the way that I learn. I like learning new things, and having done so in a relatively wide variety of areas (painting, music, education, math, algorithms, poetry, design), I wanted to share what works for me when I come across new stuff to learn. To clarify, this is <b>not </b>deliberate practice. Deliberate practice is about becoming great at something over a long period of time. I want to focus on something much more common and useful for me: becoming reasonably proficient at something quickly.<br />Let's call it <i>deliberate learning</i>.<br /><h4><br />1. Choose a mentor and follow blindly, for a limited time</h4><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://upload.wikimedia.org/wikipedia/en/9/9b/Yoda_Empire_Strikes_Back.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="200" src="https://upload.wikimedia.org/wikipedia/en/9/9b/Yoda_Empire_Strikes_Back.png" width="173" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">For a limited time, blindly follow you will</td></tr></tbody></table>This seems to me particularly useful, while being quite challenging for anyone with a critical mind. It's also very obvious and most people do it to some extent, but it's a good idea to do so consciously as it allows us to switch it on when we need to learn something, whereas the natural tendency, especially with age, is to do it less and less, mostly due to ego.<br /> The idea is to find a teacher, who may be someone teaching you a course at the university, a colleague at work, or even your superior. This person should be very experienced and much better than you at what you're trying to learn, and should be available to you on a regular basis. You should buy into this person's point of view on the subject you're trying to learn: imitate this person's methods, ask for advice, ask questions, and just believe everything they tell you (professionally). For the limited time that you're adopting this person as your mentor, you should also suspend your disbelief about their professional shortcomings. It is a surprisingly powerful approach, as it let's you really run with ideas and concepts along a path someone else already paved, and with their help. After the limited time has passed (e.g., the university term), you can reevaluate all the stuff you used to embrace, and gradually throw away whatever you disagree with, or adapt it to your own style. One last point: this mentor doesn't have to be a person - it may even be a book.<br /><br /><h4>2. Steer toward the boring and the difficult</h4><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://4.bp.blogspot.com/-brWmoznF41w/V291XFUz4hI/AAAAAAAAC_c/zU2B0xY7628PY7PVXS-rg96b5J6sJxk_ACLcB/s1600/Imagewilkywonka.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="198" src="https://4.bp.blogspot.com/-brWmoznF41w/V291XFUz4hI/AAAAAAAAC_c/zU2B0xY7628PY7PVXS-rg96b5J6sJxk_ACLcB/s200/Imagewilkywonka.jpg" width="200" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Boring <b>and </b>difficult? Do go on!</td></tr></tbody></table><div>Like the mentor thing, this is about suspending the self for a while. After you finish your learning period on the subject (I know the common wisdom is one should always be learning, but very rarely can one maintain a state of learning about everything) you'll naturally stay away from the stuff that bores you or that you don't understand well. This means that now is the only time you'll have to gain some ground in these areas. This being a learning period, you're also relatively energetic, and can muster the courage to face those areas, so it is very literally now or never. So be on the lookout for boring or difficult topics, and fearlessly dive into them. Your environment (at work or school) knows you're just learning, so it will be more forgiving to failure, which is inevitable when trying new and difficult things.</div><br /><h4>3. Get people whose judgement you trust to criticize your work frequently</h4><div class="separator" style="clear: both; text-align: center;"></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://vignette2.wikia.nocookie.net/gameofthrones/images/5/57/Tyrion_4x07.jpg/revision/latest?cb=20160130073841" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="112" src="https://vignette2.wikia.nocookie.net/gameofthrones/images/5/57/Tyrion_4x07.jpg/revision/latest?cb=20160130073841" width="200" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">My work sucks? I demand a trial by combat!</td></tr></tbody></table>This is obviously necessary, and naturally hard on the ego, so encourage yourself with the following as you go:<br />- Paraphrasing <i><a href="https://www.youtube.com/watch?v=y48hZ_rGsP4">Fight Club</a></i> - you are not your work, so your work can and will suck sometimes, which doesn't mean you, in general, do.<br />- Going from terrible to okay is way easier than going from good to great, so if your work is shitty, this is good news as it means with little work you can improve a lot.<br />- Crummy work counts for experience too, so it wasn't a waste of time.<br /><br />Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-71088956635016219252016-06-07T17:30:00.000+03:002016-06-26T06:14:05.112+03:00The God Awful UX of Israeli Train StationsIt does not take a UX expert to see that the electronic ticket validation system in Israel Railways is poorly designed.<br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-Q33XXV5uqfo/V1bO1Lq2q-I/AAAAAAAAC_E/5hGdmdgDc64Xoe11TDZHHE_J6moRvbEhwCLcB/s1600/train_israel_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://2.bp.blogspot.com/-Q33XXV5uqfo/V1bO1Lq2q-I/AAAAAAAAC_E/5hGdmdgDc64Xoe11TDZHHE_J6moRvbEhwCLcB/s320/train_israel_1.png" width="320" /></a></div><br />Here's how its designers apparently expect it to be used:<br />- The passenger walks along the lane (1).<br />- The rotating bar (2) lies about 70cm above ground, and is locked in position until the ticket is validated.<br />- The passenger presses the ticket against the screen (3).<br />- The ticket is successfully validated, the passenger pushes the bar (2) that subsequently rotates to allow the passenger to enter the ramp.<br /><br />Well, it doesn't exactly play out that way.<br />About 50% of the time the ticket isn't validated correctly and the rotating bar is locked in place, leaving the passenger stumbling against it, delaying a group of annoyed people standing behind him or her.<br />Why isn't the passenger validating again? Well, indeed an error message is shown on the screen, and there's also some kind of beep to indicate something went wrong, but none of this matters because:<br />1) <b>The ever-so-gentle beeping sound is inaudible</b> in any average train station.<br />2) <b>The screen is parallel to the passenger's field of vision</b>, so one has to bend backward to see it.<br />3) <b>The screen is often blocked at this point by the passenger's own hand</b> holding the ticket against it to be validated.<br />4) <b>The screen is almost always dirty</b> because - again - this is where people stick their hand/wallet to validate.<br /><br />All this together means that every other passenger gets stuck in the lane. It takes a couple of seconds to figure out that waiting a bit longer isn't fixing it, thereby delaying all other passengers. To top it all, every subsequent validation attempt takes a couple of seconds more than it should - <u>due to the same design flaws</u>. I get annoyed all over again just writing this!<br /><br />Mind you, this is not some ground-breaking product that provides completely new design challenges. It's not as if trains or electronic tickets were invented by Israel Railways. Rather, there are tons of examples to research from all over the world!<br /><br />It's one of those cases where poor design makes hundreds of thousands of people's daily routine just that much more annoying, as we are helplessly victimized by the laziness and just general inadequacy of others.Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-76282559871944923552016-05-18T08:10:00.000+03:002016-05-18T08:10:24.183+03:00Triangular numbers, a 3D cube, and the octahedral groupFor some computational geometry project, I had to understand the orbits of the action of the <a href="https://en.wikipedia.org/wiki/Octahedral_symmetry">octahedral group</a> on a 3D cube, and like so many times with math, I did it the hard way only to find out later that a simple observation would have saved me the effort. Well, some of the effort.<br /><br /><h4>tl;dr</h4><div>Upon counting the orbits of the cells of a 3D cube under the octahedral group action, I found out the result is a sum of triangular numbers, which has a very intuitive geometric reason.</div><div><br /></div><h4>The gory details</h4>The octahedral group can be thought of as the group of symmetries obtained by applying a series of 90-degree rotations and/or face-parallel reflections to a cube. Another way of thinking about it is this: if the cube is centered at the origin, applying an element of the group to the cube is equivalent to shuffling the coordinates and/or multiplying some of the coordinates by $-1$. Since there are 6 permutations of the coordinates, and 8 choices as to which coordinates to multiply by $-1$, the number of elements in the group is 48.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-qDRTENDcy4U/VzsGVK_9xBI/AAAAAAAAC9g/3zcgtPUcpbAINn1BWKJILFHeqgzUGP_mgCLcB/s1600/grid.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="193" src="https://2.bp.blogspot.com/-qDRTENDcy4U/VzsGVK_9xBI/AAAAAAAAC9g/3zcgtPUcpbAINn1BWKJILFHeqgzUGP_mgCLcB/s200/grid.png" width="200" /></a></div><br />For simplicity, let's assume that the 3D cube is actually a discrete object, comprised of $n^3$ cells for some even value of $n$ (having an odd $n$ doesn't change the outcome by a lot, but is a bit different). The group action breaks the cube into orbits, for example, the corner cells form a single orbit of size 8. Note that the group elements can be also thought of as $3\times 3$ matrices, all of whose determinents are $1$ or $-1$ (the latter if the element induces a reflection), and the action thus preserves norms. To put it plainly, the distance of a cell from the cube's center is an invariant of the group action. This observation means that we can think of the cube as comprised of $\frac n 2$ nested hollow cubes of dimensions $n\times n \times n, (n-2)\times(n-2)\times(n-2), ... 4\times 4\times 4, 2\times 2\times 2$, sort of like a matryoshka doll of 3D cubes.<br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://3.bp.blogspot.com/-Ms_OYzKhMas/Vzv0Xgt_ENI/AAAAAAAAC90/GuuvCMIqDlMLzpiON_eLXKRvD4GFRZZdACLcB/s1600/Selection_160.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://3.bp.blogspot.com/-Ms_OYzKhMas/Vzv0Xgt_ENI/AAAAAAAAC90/GuuvCMIqDlMLzpiON_eLXKRvD4GFRZZdACLcB/s1600/Selection_160.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Image credit: Wikipedia</td></tr></tbody></table><br />It suffices to understand how the group acts only on one of these hollow cubes, so let's examine only the largest one - the $n\times n\times n$ hollow cube.<br /><br /><h4>Classifying orbits</h4>Suppose the cells are indexed w.r.t. the center of cube, so each cell is indexed by some $i, j, k\in \{-\frac n 2,..., \frac n 2\}\setminus \{0\}$ such that at least one of $i, j, k$ is $\pm \frac n 2$. We omit zero because $n$ is even and no cell is the center cell of the cube.<br />Observe that using this notation, together with thinking of the group elements as permuting coordinates and/or pointwise multiplying them by $-1$, makes it evident that, up to a permutation, there are only 4 cases, or types of orbits:<br /><span style="background-color: red;">Case 1</span>: $\frac n 2 = |i| \neq |j|, |i|\neq |k|, |j| \neq |k|$, choosing such indices defines an orbit of size 48, since no permutation of the coordinates or multiplication of them by $-1$ leaves the indices as they were.<br /><span style="background-color: orange;">Case 2</span>: $i = |j| = |\frac n 2|, |j|\neq |k|$, these are all the cells that lie on the edges of the hollow cube. A cell with such indices is invariant under elements switching $i$ and $j$, so its orbit's size is 24. To be precise, in the case where $j = -i = \pm \frac n 2$, swapping $i$ and $j$ is just like pointwise multiplying both by $-1$, so the orbit is obtained simply by moving $k$ around and pointwise multiplication by $-1$, and indeed the orbit size is 24.<br /><span style="background-color: yellow;">Case 3</span>: $|i| = |j|, |j| < |k| = \frac n 2$, these are all the cells that lie on the diagonals that run along the face of the hollow cube. For the same arguments as Case 2 - the orbit size here is 24.<br /><span style="background-color: lime;">Case 4</span>: $|i| = |j| = |k| = \frac n 2$, these are the corner cells. The difference between two corners is only the sign of the coordinates, so the size of such an orbit is 8.<br /><br /><h4>Counting orbits</h4>It is now left to understand how many orbits there are for each case. We choose a representative for each orbit - $(i, j, k)$, and count those.<br /><span style="background-color: red;">Case 1</span>: The choice is of some unordered pair of elements from $\{1,2,...,\frac n 2 - 1\}$. The pair is unordered since the group action puts $(i,j,k)$ in the same orbit as $(j,i,k)$, and we omit the negatives since they are obtained via the pointwise multiplication by $-1$. The number of ways to choose such a pair is therefore $\frac 1 2 (\frac n 2 - 1)(\frac n 2 - 2)$.<br /><span style="background-color: orange;">Case 2</span>: Since $|j|$ and $|i|$ must be equal to $\frac n 2$, the only choice here is of $1\leq k < \frac n 2$ (negative values of $k$ are obtained via the pointwise multiplication by $-1$ of the group action). So clearly there are $\frac n 2 - 1$ of those.<br /><span style="background-color: yellow;">Case 3</span>: Like Case 2, the only choice here is of $1 \leq |i| < \frac n 2$, which in turn determins $|j|$. So there are $\frac n 2 - 1$ such orbits.<br /><span style="background-color: lime;">Case 4</span>: This is the corners' orbit, so there is exactly one for a hollow cube.<br /><br />Putting it together, a hollow 3D cube of dimension $n$ has $\frac 1 2 (\frac n 2 - 1)(\frac n 2 - 2) + 2 \cdot (\frac n 2 - 1) + 1 = \frac 1 8 (n^2 + 2n)$.<br />Since the full 3D cube, with an even dimension $s$, is comprised of $\frac s 2$ such hollow cubes, the number of orbits is: $\frac 1 8 \sum _{n=1} ^{\frac s 2} ((2n)^2 + 2(2n))$, which surprisingly gives us a sum of triangular numbers $\sum_{n=1} ^{\frac s 2} \frac {n(n+1)} 2$, which has a nice closed form $\frac {\frac s 2 \cdot (\frac s 2 + 1) \cdot (\frac s 2 + 2)} 6$.<br /><br /><h4>Why triangular numbers?</h4>This is a satisfyingly clean formula to ed up with, after a tedious computation, and as one would expect, it is so for a reason:<br />As noted in the previous paragraph, the result is a sum of triangular numbers, which are called thus because they also represent the number of blocks you'd use to construct a triangle where the bottom row has $n$ blocks, the next row has $n-1$ blocks and so on.<br />The image below shows one representative of each orbit in the outer layer of an $8\times 8 \times 8$ cube. The <span style="background-color: #cc0000;">Case 1</span> representatives are red, <span style="background-color: orange;">Case 2</span> - orange, <span style="background-color: yellow;">Case 3</span> - yellow, and <span style="background-color: lime;">Case 4</span> - green.<br /><br />And indeed these representatives form a triangle, and the sum of triangles really represents (sort of) a pyramid that goes from the outer layer of the cube inward, the colorful part of the image below being its base.<br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-yDXTKCc8KHA/VzsF6S8FY9I/AAAAAAAAC9c/GwlWpjvY16YQrU4pO4Tf_dQeQ05IalXjgCLcB/s1600/Selection_159.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://2.bp.blogspot.com/-yDXTKCc8KHA/VzsF6S8FY9I/AAAAAAAAC9c/GwlWpjvY16YQrU4pO4Tf_dQeQ05IalXjgCLcB/s1600/Selection_159.png" /></a></div><br /><div><br /></div>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-38624263123568195582016-04-28T23:30:00.001+03:002016-04-29T06:34:20.852+03:00Powers of Graphs Are Almost Always Hard<div dir="rtl" style="text-align: right;" trbidi="on"><div dir="ltr" style="text-align: left;">Early in 2011, I spent a few months as an exchange student in the University of Melbourne. Although I was writing my thesis at the time, I was looking for topics for a small-scale research, as I had to turn in some written assignment as part of the exchange program. I can't remember why, but I thought a bit about powers of graphs, and pondered about their relation to hardness. Since it turned out to be an easy question to solve, it wasn't enough for the written assignment (let alone a research paper), but I do have a warm spot for it, so here it is:<br /><br />(If you are browsing on mobile, switch to desktop view to display the math stuff nicely)</div><div dir="ltr" style="text-align: left;"><br /></div><h4 style="text-align: left;">Background: Powers of Graphs </h4><div dir="ltr" style="text-align: left;">Given a <a href="http://mathworld.wolfram.com/SimpleGraph.html">simple graph</a> (we restrict our discussion to this type for brevity) $G(V, E)$, we define $G^2$ by adding an edge between every two vertices $v,j\in V$ if there exists some $w\in V$ such that $\{v, w\} \in E$, and $\{u, w\} \in E$.</div><div dir="ltr" style="text-align: left;">In other words - if there was a path of length 2 between $v$ and $u$ in $G$, then there's an edge between them in $G^2$. This works similarly for $G^3$ (where paths of length 3 or less in $G$ become edges) and so on. </div><div dir="ltr" style="text-align: left;">Clearly, if the longest distance in the graph is of length $d$ (in which case we say that $d$ is the <i>diameter</i> of $G$), then $G^d$ is simply a clique, since all paths in $G$ are at most of length $d$.</div><div dir="ltr" style="text-align: left;"><br /></div><div dir="ltr" style="text-align: left;"><h4>Background - Independent Set</h4></div><div dir="ltr" style="text-align: left;">Given a graph $G(V, E)$, an independent set of vertices is some $U\subseteq V$ such that $u,v\in U \Rightarrow \{u,v\}\notin E$. Finding a <i>maximum</i> independent set (i.e. largest in size, not to be confused with <i>maximal</i> which means it is not strictly a subset of any other independent set) in a graph is known to be NP-hard, and also hard to approximate.<br /><br /><h4>So here's the question:</h4></div><div dir="ltr" style="text-align: left;"> In a clique, every vertex is a maximum (and also maximal) independent set, so for every simple graph $G$ with diameter $d$, solving the independent set problem for $G^d$ is easy: just choose any vertex you like, and you're done. This raises the question - if a problem is in general hard on $G$, but easy on $G^d$, how hard is it for $G^k$ where $k < d$? I mean, at which point does this very hard problem becomes trivial? </div><div dir="ltr" style="text-align: left;"><br /></div><div dir="ltr" style="text-align: left;">I'll save you the suspense - independent set is generally hard on $G^{d-1}$, so the problem is not all that interesting, and the hardness of independent set on powers of graphs is basically: hard, hard, hard, ... , hard, trivial. Not an exciting result, I admit, but let's prove it anyway.<br /><br /></div><div dir="ltr" style="text-align: left;"><h4>Proof by Reduction</h4><div>Proof sketch: given a graph $G$, we'll construct a graph $H$, that is only slightly larger than $G$, has the same diameter, and is such that solving the independent set problem for $H^{d-1}$ will give us the solution for $G$.</div><div><br /></div><div>First, the case of an even $d$, which is simpler:</div><div>Denote $G$'s vertices by $v_1, v_2, ... , v_n$, we construct $H$ by taking $n$ disconnected vertices denoted $u_1, u_2, ..., u_n$ - we'll call those the 'old' vertices - and adding $n\cdot (\frac d 2 - 1)$ 'new' vertices to them in the following manner:</div><div><b>1.</b> Add one special vertex $c$.</div><div><b>2.</b> For every $i : 1\leq i \leq n$, connect $u_i$ to $c$ by a path of length $\frac d 2$ using $\frac d 2 - 1$ of the 'new' vertices (all of these paths should be disjoint, and that's okay, since we have exactly $n\cdot (\frac d 2 - 1)$ of these new vertices). Denote the vertices of the path from $c$ to $u_i$: $c\rightarrow u_i ^1 \rightarrow u_i ^ 2 \rightarrow ... \rightarrow u_i ^ {\frac d 2 - 2} \rightarrow u_i ^{\frac d 2 - 1} \rightarrow u_i$.</div><div><b>3.</b> For every $\{v_k, v_j\} \in E$ that form an edge in $G$, add to $H$ the edge $\{u_k ^1, u_j ^1\}$.</div><div> $H$ is thus sort of a big star graph, having $c$ in the middle, with some additional edges due to step (3) above.</div><div><br /></div><div><u>A few observations</u>:</div><div><b>1.</b> For every two vertices of the original graph $\{v_l,v_t\}\notin E$, the shortest path from $u_l$ to $u_j$ in $H$ goes through $c$ and is of length $d$. It follows that the diameter of $H$ is at least $d$.</div><div><b>2.</b> In $H^{d-1}$, all of the new vertices form a clique, and each of them is connected by an edge to each of the old vertices. The diameter of $H$ is therefore at most $d$, and so it is exactly $d$. </div><div><b>3.</b> It follows that a maximum independent set in $H^{d-1}$ cannot contain any of the new vertices.</div><div><b>4.</b> $\{u_j, u_k\}$ is an edge in $H^{d-1}$ <i>if and only if </i>$\{v_j, v_k\}$ is an edge in $G$, so every independent set in $G$ correlates to an independent set of 'old' vertices in $H^{d-1}$ and vice versa. </div><div>Putting all these observations together boils down to the fact tha every maximum independent in $H^{d-1}$ correlates to a maximum independent set in $G$ and vice versa.</div><div><br /></div><div>What about an odd $d$? well, instead of a single vertex serving as the center, we use a clique of n vertices that serves as center of $H$, and everything else works very much the same.</div><div><br /></div><div>Note that a slight tweak can be used to show that $H^{d-2}$ is no easier, and so on.</div><div><br /></div><div>So, alas, independent set is hard on all but the $d$-th power of a graph, in which case it is trivial.</div><div><br /></div><div><br /></div></div></div>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-74385906448609362522016-01-31T15:00:00.002+02:002016-02-01T09:51:29.477+02:00NP-Complete Problems as Repeatable Math Puzzles <div dir="rtl" style="text-align: right;" trbidi="on"><div dir="ltr" style="text-align: left;"><br /></div><h3 dir="ltr" style="text-align: left;">Repeatable Puzzles</h3><div dir="ltr" style="text-align: left;"> In the 3 years I worked at <a href="https://www.matific.com/">Matific</a>, I was involved in designing all of the mini-games (we called them 'episodes') produced by the company. This meant that I spent a non-negligible part of my time on the hunt for math puzzles that are</div><div dir="ltr" style="text-align: left;"></div><ul dir="ltr" style="text-align: left;"><li>interesting and rewarding to solve</li><li>rely only on elementary school math knowledge</li><li>worth playing over and over, with respect to the above</li></ul><div dir="ltr" style="text-align: left;">Most of the really cool puzzles, such as determining which - out of 12 coins - was fake, using a balance scale and only 3 weighings, fall short of the "worth repeating" notion, as there's no real pleasure or challenge in <a href="http://mathforum.org/library/drmath/view/55618.html">solving</a> them a second time. So googling "Math Puzzles" and reading puzzle books, though fun, was often of little use.</div><div dir="ltr" style="text-align: left;"><br />As time went by, and development progressed, puzzles turned out to be only a small part of what we did. A typical episode was rather required to help in understanding some deeper principal of a previously taught skill, via hands-on experience, which I think we managed to do well, and that's a topic for another post. </div><div dir="ltr" style="text-align: left;"><br />Nevertheless, there were some puzzles in the mix, for example: a game where the user is given 4-5 numbers (e.g. 2, 3, 4, 7), and is asked to get to a target number (e.g. 23) using the some of the four operations and each of the initial numbers (e.g. 4/2 + 3*7).<br /><br /></div><div dir="ltr" style="text-align: left;">Another puzzle, for 1st graders, asked the student to arrange toys on shelves, subject to some constraints, e.g. - the doll must be above the teddybear, the car has to be to the right of the dinosaur, and so on.<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-x3SOLPI8we0/Vq4D6oi4vPI/AAAAAAAAC8A/SFJ5hIAaUEc/s1600/Selection_103.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="http://2.bp.blogspot.com/-x3SOLPI8we0/Vq4D6oi4vPI/AAAAAAAAC8A/SFJ5hIAaUEc/s320/Selection_103.png" width="320" /></a></div><br />A third puzzle was simply variants of a well known water-pouring puzzle: one has 2-3 containers, each of different volume (e.g. 5L and 3L) and the objective is to obtain another quantity (e.g. 4L) via pouring and filling.<br /><br /><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/5_MoNu9Mkm4/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/5_MoNu9Mkm4?feature=player_embedded" width="320"></iframe></div><h3 style="text-align: left;"><br />Starting With the Solution</h3> As we designed more of those repeatable puzzles, a few common traits emerged:<br /><br /><ul style="text-align: left;"><li> they involved a more than one skill. The pouring puzzles, for example, involves addition, subtraction, understanding of volume, and strategizing.</li><li> we had to generate problems with well-tuned difficulty levels.</li></ul><div>Let me focus on that last one: When one designs a puzzle, the first instinct may be to randomize the problem (e.g. how much water in each container? what is the target quantity?) and then write a solver that solves it, but that is rarely the right thing to do, for two reasons: 1) This leaves the difficulty level to chance, 2) Sometimes the problem has no quick solver, and the solver will needs to go over all possibilites to find the solution, or reach a conclusion that it has no solution, in which case a new problem has to be generated at random and checked and so on. Our standard strategy, which applied to most of the cases, was starting from the solution. </div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-yWKK-TF3_-g/Vq4ETwRaifI/AAAAAAAAC8I/FNMa8b-jEBY/s1600/Selection_104.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="201" src="http://1.bp.blogspot.com/-yWKK-TF3_-g/Vq4ETwRaifI/AAAAAAAAC8I/FNMa8b-jEBY/s320/Selection_104.png" width="320" /></a></div><br />For example, choose 4 random numbers in some range, e.g. 2, 5, 9, 11, and now choose operations at random, e.g. *, +, -, which gets 2 * 5 + 9 - 11 = 8. And so we present the user with the numbers 2, 5, 9, 11, setting 8 to be the target number. This approach has its drawbacks, such as producing problems using a certain solution while a simpler one exists, but they are less severe, product-wise.<br />This "start from the solution" approach took us a while to figure out, in which time we tried the naive approach, of randomizing a problem and running a solver. After a few of these, I noticed that we often realize that the problem is NP-hard, or in some cases assume it is so, not being sure how to prove it. A solver for such puzzles is problematic and can't scale to larger instances of the problem, especially seeing how the code had to be very light-weight to run on a browser. Lastly, a crucial part of programming a puzzle is checking the user's solution, which was almost always considerably easier than generating the problem. And so at some point it became clear to me that many of our so-called puzzles, were simply instances of NP-complete problems.<br />This was neat because it gave us something to draw inspiration from, in addition to poring over puzzle books. <br /><br /><h3 style="text-align: left;">Some Thoughts </h3> I think that what makes NP-complete problems such useful puzzles is that they somehow seem to come from the real world, at least more than those in harder complexity classes, which means many of them can be explained to a layman in a minute. The NP-completeness also means that there's no trick that the user learns once, and is then bored by subsequent puzzles that are solved using that same trick. Being in NP also means that solutions can be checked easily, so the software can check the user's solution, but also, when the user fails - and the software shows a correct solution, the user can see very quickly that it is correct. Lastly, they encourage a heuristic cross-topical approach to problem solving, which is to say there's no title saying "this is a subtraction problem, solve it using subtraction". Both the method and the tools used by the user (or student) are not part of the problem's definition, and that is how math usually presents itself in real life.</div><div dir="ltr" style="text-align: left;"><br /></div></div>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0tag:blogger.com,1999:blog-642244788469558745.post-38477344324800474732015-12-23T17:13:00.001+02:002015-12-28T18:52:09.729+02:00Casting to double is faster than Kahan's summation<div dir="rtl" style="text-align: right;" trbidi="on"><h3 dir="ltr" style="text-align: left;">A floating problem</h3><div dir="ltr" style="text-align: left;">Floating point precision problems are notoriously annoying, and personally I was somewhat surprised they are still an issue in this day and age, but they are.<br />For instance, by the end of the following code:</div><pre dir="ltr" pre="" style="text-align: left;"><pre><span style="color: maroon; font-weight: bold;">float</span> x <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: purple;">;</span><br /><span style="color: maroon; font-weight: bold;">float</span> f <span style="color: #808030;">=</span> <span style="color: green;">1e-6</span><span style="color: purple;">;</span><br /><span style="color: maroon; font-weight: bold;">for</span> <span style="color: #808030;">(</span><span style="color: maroon; font-weight: bold;">unsigned</span> i <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: purple;">;</span> i <span style="color: #808030;"><</span> <span style="color: green;">1e6</span><span style="color: purple;">;</span> <span style="color: #808030;">+</span><span style="color: #808030;">+</span>i<span style="color: #808030;">)</span><br /> x <span style="color: #808030;">=</span> x <span style="color: #808030;">+</span> f<span style="color: purple;">;</span></pre></pre><div dir="ltr" style="text-align: left;"><div style="text-align: left;">x's value will be 1.00904 and not 1.</div><div style="text-align: left;">Even much simpler code reveals the issue:</div></div><pre dir="ltr" pre="" style="background: rgb(255, 255, 255); text-align: left;"><span style="color: maroon; font-weight: bold;">float</span> x <span style="color: #808030;">=</span> <span style="color: green;">1e6</span><span style="color: purple;">;</span><br /><span style="color: maroon; font-weight: bold;">float</span> y <span style="color: #808030;">=</span> <span style="color: green;">1e-6</span><span style="color: purple;">;</span><br /><span style="color: maroon; font-weight: bold;">float</span> z <span style="color: #808030;">=</span> x <span style="color: #808030;">+</span> y<span style="color: purple;">;</span></pre><div dir="ltr" style="text-align: left;"><div style="text-align: left;"><br /></div><div style="text-align: left;">z's value here will be exactly 1,000,000 and not 1,000,000.000001.</div><div style="text-align: left;">The reason for this is that 32 bit (the number of bits used for a float type) can represent a number to a limited precision, and so it makes sense to use them for high precision when representing small numbers, and to sacrifice that precision gradually as the integral part of the number increases.</div><div style="text-align: left;"><br /></div><h3 style="text-align: left;">Why use floats when you can use doubles?</h3><div style="text-align: left;">Well, in many cases, doubles simply solve the problem. Double is also a finite representation, but is far more precise than float. The smallest positive number a float can represent is about 1e-38, whereas for a double it's something around 2e-308. To emphasize, the ratio between the two is something like 1e270 which is considerably more than the number of atoms in the universe raised to the third power.<br />The reason is that floats occupy half the space as doubles, and when writing a code that is meant to be vectorized by the compiler, which one often does in high performance computing, this can translate to a factor of 2 speed up. Additionally, if your data is basically a bunch of real numbers, it would also mean your data in floats is around half the size of your data in doubles, so transmitting it over a network may be twice as fast, and so on.<br /><br /><h3 style="text-align: left;">Kahan's summation algorithm</h3><div style="text-align: left;">For running sums, William Kahan suggested the following algorithm, cleverly using a second variable to keep track of the deviation from the "true" sum (the following snippet is <a href="https://en.wikipedia.org/wiki/Kahan_summation_algorithm">from Wikipedia</a>, and not in C++, but straightforward nevertheless):</div><div style="text-align: left;"><br /></div><pre style="background-color: #f9f9f9; border: 1px solid rgb(221, 221, 221); font-family: monospace, Courier; font-size: 14px; line-height: 1.3em; padding: 1em; white-space: pre-wrap;"><b>function</b> KahanSum(input)<br /> <b>var</b> sum = 0.0<br /> <b>var</b> y,t // Temporary values.<br /> <b>var</b> c = 0.0 // A running compensation for lost low-order bits.<br /> <b>for</b> i = 1 <b>to</b> input.length <b>do</b><br /> y = input[i] - c // So far, so good: <i>c</i> is zero.<br /> t = sum + y // Alas, <i>sum</i> is big, <i>y</i> small, so low-order digits of <i>y</i> are lost.<br /> c = (t - sum) - y // <i>(t - sum)</i> recovers the high-order part of <i>y</i>; subtracting <i>y</i> recovers -(low part of <i>y</i>)<br /> sum = t // Algebraically, <i>c</i> should always be zero. Beware overly-aggressive optimizing compilers!<br /> <b>next</b> i // Next time around, the lost low part will be added to <i>y</i> in a fresh attempt.<br /> <b>return</b> sum</pre><div style="text-align: left;"><br /></div><div style="text-align: left;">And this is, in my opinion, really beautiful. </div><div style="text-align: left;">However, as it turns out:</div><h3 style="text-align: left;">Casting to double is faster</h3><div>As it turns out, the dumber, less beautiful solution, is faster:</div><div><pre style="background: rgb(255, 255, 255);"><span style="color: maroon; font-weight: bold;"><br /></span></pre><pre style="background: rgb(255, 255, 255);"><pre style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial;"><span style="color: maroon; font-weight: bold;">double</span> x <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: purple;">;</span><br /><span style="color: maroon; font-weight: bold;">float</span> f <span style="color: #808030;">=</span> <span style="color: green;">1e-6</span><span style="color: purple;">;</span><br /><span style="color: maroon; font-weight: bold;">for</span> <span style="color: #808030;">(</span><span style="color: maroon; font-weight: bold;">unsigned</span> i <span style="color: #808030;">=</span> <span style="color: #008c00;">0</span><span style="color: purple;">;</span> i <span style="color: #808030;"><</span> <span style="color: green;">1e6</span><span style="color: purple;">;</span> <span style="color: #808030;">+</span><span style="color: #808030;">+</span>i<span style="color: #808030;">)</span> <span style="color: purple;">{</span><br /> x <span style="color: #808030;">=</span> x <span style="color: #808030;">+</span> f<span style="color: purple;">;</span> <span style="color: dimgrey;">// f is implicitly cast to double here</span><br /><span style="color: purple;">}</span></pre></pre></div></div><div style="text-align: left;"><br />I ran some experiments, and for a very large set of numbers (adding 1e10 numbers, each equal to 1e-7), casting to double was twice as fast as using Kahan's summation algorithm.<br />A cool algorithm, though.</div></div></div>Shir Peledhttp://www.blogger.com/profile/09979031232145173473noreply@blogger.com0