{"id":8507,"date":"2022-04-12T20:07:00","date_gmt":"2022-04-13T00:07:00","guid":{"rendered":"https:\/\/blogs.mathworks.com\/cleve\/?p=8507"},"modified":"2022-04-12T20:07:00","modified_gmt":"2022-04-13T00:07:00","slug":"digital-simulation-of-rubiks-cube-with-qube","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/cleve\/2022\/04\/12\/digital-simulation-of-rubiks-cube-with-qube\/","title":{"rendered":"Digital Simulation of Rubik&#8217;s Cube with Qube"},"content":{"rendered":"<div class=\"content\"><!--introduction--><p>This blog post describes <tt>Qube<\/tt>, my Rubik's Cube simulator. Source code for <tt>Qube<\/tt> is now available in <i>one single file<\/i> from this link: <a href=\"https:\/\/blogs.mathworks.com\/cleve\/files\/Qube_osf.m\">Qube_osf.m<\/a>. I will also submit the code to the MATLAB Central File Exchange. As usual, I welcome any feedback.<\/p><!--\/introduction--><h3>Contents<\/h3><div><ul><li><a href=\"#c9bf6fd5-cb12-4713-81b3-dfc44b70b387\">Qube<\/a><\/li><li><a href=\"#6fef7c45-0afd-4d20-8fc0-79674a882445\">cube<\/a><\/li><li><a href=\"#04f8e6f4-7585-466c-93ef-65572229c3c5\">stack<\/a><\/li><li><a href=\"#dd55d966-37da-417f-b887-f896649f9440\">keys<\/a><\/li><li><a href=\"#2b2e660c-c4d6-40b0-a68e-46dc9dba3834\">Scramble<\/a><\/li><li><a href=\"#b5e7fd32-eb4e-44f8-af0e-f3a8b337116f\">Unscramble<\/a><\/li><li><a href=\"#4d898085-5cf5-41b2-8ff8-59b561e7a266\">Appearance<\/a><\/li><li><a href=\"#1b258923-a5b5-4a48-ae3d-d9537ae2ec9d\">Actions<\/a><\/li><li><a href=\"#7796612d-ea74-4f9a-9eff-598e4a2a41a7\">Upper left-hand side<\/a><\/li><li><a href=\"#464f860e-cc06-41ac-b984-f44ec3c32e43\">Upper right-hand side<\/a><\/li><li><a href=\"#3e66904e-0cd1-4d55-9947-a18f89547137\">Software<\/a><\/li><\/ul><\/div><h4>Qube<a name=\"c9bf6fd5-cb12-4713-81b3-dfc44b70b387\"><\/a><\/h4><p>Here is the opening screen for <tt>Qube<\/tt>.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/Qube.png\" alt=\"\"> <\/p><h4>cube<a name=\"6fef7c45-0afd-4d20-8fc0-79674a882445\"><\/a><\/h4><p>The cube is displayed in the center of the simulator.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/center.png\" alt=\"\"> <\/p><h4>stack<a name=\"04f8e6f4-7585-466c-93ef-65572229c3c5\"><\/a><\/h4><p>The current stack is displayed in this text box over the cube.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/stack.png\" alt=\"\"> <\/p><h4>keys<a name=\"dd55d966-37da-417f-b887-f896649f9440\"><\/a><\/h4><p>Eighteen <tt>keys<\/tt> use Singmaster notation to generate rotations that are pushed onto the stack.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/keys.png\" alt=\"\"> <\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/Q6_stack.png\" alt=\"\"> <\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/Q6_center.png\" alt=\"\"> <\/p><h4>Scramble<a name=\"2b2e660c-c4d6-40b0-a68e-46dc9dba3834\"><\/a><\/h4><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/scramble.png\" alt=\"\"> <\/p><p>The two buttons at the lower right scramble the cube. The <tt>=&gt;<\/tt> button applies any rotations in the stack to the current cube.  To apply them to <tt>Q0<\/tt>, use <tt>Q0<\/tt> before <tt>=&gt;<\/tt><\/p><p>The <tt>==&gt;<\/tt> button is a toggle that generates repeated random rotations until it is turned off. A fresh scramble is produced every time I publish this file.<\/p><pre class=\"codeinput\">    show_randdo(3,3)\r\n    snapnow\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/Qube_Blog_No2_01.png\" alt=\"\"> <h4>Unscramble<a name=\"b5e7fd32-eb4e-44f8-af0e-f3a8b337116f\"><\/a><\/h4><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/unscramble.png\" alt=\"\"> <\/p><p>The two buttons at the lower left unscramble the cube. The <tt>&lt;=<\/tt> button generates a rotation in the direction opposite the rotation at the top of the stack.  This acts like a backspace. The <tt>&lt;==<\/tt> toggle repeatedly backspaces until the stack is empty. This is the smart way to \"solve\" the puzzle -- remember how it was scrambled.<\/p><p>Let's unscramble the cube and get back to <tt>Q0<\/tt>.<\/p><pre class=\"codeinput\">    show_undo(3,3)\r\n    snapnow\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/Qube_Blog_No2_02.png\" alt=\"\"> <h4>Appearance<a name=\"4d898085-5cf5-41b2-8ff8-59b561e7a266\"><\/a><\/h4><p>The buttons in the left-hand group control the appearance of the simulator.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/lhs.png\" alt=\"\"> <\/p><p><b>width<\/b><\/p><p>The vertices of the basic unit cubelet, <tt>qzero<\/tt>, are the eight combinations of +1 and -1, so the half-width of <tt>qzero<\/tt> is one. The twenty-seven cubelets in <tt>Q0<\/tt> are scaled by this <tt>width<\/tt> parameter to produce gaps between the individual cubelets.<\/p><pre class=\"codeinput\">    show_width(1,3)\r\n    snapnow\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/Qube_Blog_No2_03.png\" alt=\"\"> <p><b>nstep<\/b><\/p><p>The number of fractional rotations in a quarter turn controls <tt>Qube's<\/tt> speed.<\/p><p><b>type<\/b><\/p><p>The cubelet centers are the points <tt>[x,y,z]<\/tt> where <tt>x<\/tt>, <tt>y<\/tt> and <tt>z<\/tt> are combinations of -2, 0 and 2.  The cubelet type is the number of nonzeros in coordinates of its center, <tt>nnz([x,y,z])<\/tt>.<\/p><pre>* 0: center\r\n* 1: face\r\n* 2: edge\r\n* 3: corner<\/pre><pre class=\"codeinput\">    show_types\r\n    snapnow\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/Qube_Blog_No2_04.png\" alt=\"\"> <p><b>color<\/b><\/p><p>An alternative to the traditional Rubik's colors made from the MATLAB axes color order.<\/p><pre class=\"codeinput\">    show_color(1,3)\r\n    snapnow\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/Qube_Blog_No2_05.png\" alt=\"\"> <p><b>mouse<\/b><\/p><p>This button turns on Handle Graphics <tt>rotate3d<\/tt>.  You can then use your mouse to rotate the viewpoint.  The visual effect is the same as rotating the entire cube.<\/p><h4>Actions<a name=\"1b258923-a5b5-4a48-ae3d-d9537ae2ec9d\"><\/a><\/h4><p>The buttons in the right-hand group initiate computations. Other tools may be added.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/rhs.png\" alt=\"\"> <\/p><p><b>solve<\/b><\/p><p>Experimental solver. Greedy algorithm to minimize the sum of SVDs of the difference between the cubelets in the current cube and cubelets in Q0.  Also known as the nuclear norm. It turns out that this solver does not work very well.<\/p><p><b>period<\/b><\/p><p>Number of repetitions to return to Q0. A fundamental notion in group theory.<\/p><p><b>reset<\/b><\/p><p>Reinitialize without restarting.<\/p><p><b>restart<\/b><\/p><p>Complete restart.<\/p><p><b>Q0<\/b><\/p><p>Restore <tt>Q0<\/tt>.<\/p><h4>Upper left-hand side<a name=\"7796612d-ea74-4f9a-9eff-598e4a2a41a7\"><\/a><\/h4><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/upper_lhs.png\" alt=\"\"> <\/p><p><b>score<\/b><\/p><p>Currently, the nuclear norm distance to Q0.  Need something more sensitive to Rubik's cube patterns.<\/p><p><b>count<\/b><\/p><p>Number of rotations.  Hence, the period.<\/p><p><b>post<\/b><\/p><p>Most recent rotation.<\/p><h4>Upper right-hand side<a name=\"464f860e-cc06-41ac-b984-f44ec3c32e43\"><\/a><\/h4><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"http:\/\/blogs.mathworks.com\/cleve\/files\/upper_rhs.png\" alt=\"\"> <\/p><p><b>help<\/b><\/p><p><tt>helpwin Qube<\/tt><\/p><p><b>info<\/b><\/p><p>Pointer to this blog post.<\/p><h4>Software<a name=\"3e66904e-0cd1-4d55-9947-a18f89547137\"><\/a><\/h4><p>The source code for <tt>Qube<\/tt> is available from this link: <a href=\"https:\/\/blogs.mathworks.com\/cleve\/files\/Qube_osf.m\">Qube_osf.m<\/a>. The <tt>osf<\/tt>, <i>one single file<\/i>,  format is a self-extracting archive that expands into a directory of individual functions.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_e088f81bace24fbc898464d501445288() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='e088f81bace24fbc898464d501445288 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' e088f81bace24fbc898464d501445288';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2022 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_e088f81bace24fbc898464d501445288()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2022a<br><\/p><\/div><!--\r\ne088f81bace24fbc898464d501445288 ##### SOURCE BEGIN #####\r\n%% Digital Simulation of Rubik's Cube with Qube\r\n% This blog post describes |Qube|, my Rubik's Cube simulator.\r\n% Source code for |Qube| is now available in _one single file_ from this link:\r\n% <https:\/\/blogs.mathworks.com\/cleve\/files\/Qube_osf.m Qube_osf.m>.\r\n% I will also submit the code to the MATLAB Central File Exchange.\r\n% As usual, I welcome any feedback.\r\n\r\n%% Qube\r\n% Here is the opening screen for |Qube|.\r\n%\r\n% <<Qube.png>>\r\n%\r\n\r\n%% cube\r\n% The cube is displayed in the center of the simulator.\r\n%\r\n% <<center.png>>\r\n\r\n%% stack\r\n% The current stack is displayed in this text box over the cube.\r\n%\r\n% <<stack.png>>\r\n\r\n%% keys\r\n% Eighteen |keys| use Singmaster notation to generate rotations\r\n% that are pushed onto the stack.\r\n%\r\n% <<keys.png>>\r\n\r\n%%\r\n% <<Q6_stack.png>>\r\n\r\n%%\r\n% <<Q6_center.png>>\r\n\r\n%% Scramble\r\n% \r\n% <<scramble.png>>\r\n% \r\n% The two buttons at the lower right scramble the cube.\r\n% The |=>| button applies any rotations in the stack to\r\n% the current cube.  To apply them to |Q0|,\r\n% use |Q0| before |=>|\r\n%\r\n% The |==>| button is a toggle \r\n% that generates repeated random rotations until it is turned off.\r\n% A fresh scramble is produced every time I publish this file.\r\n\r\n    show_randdo(3,3)\r\n    snapnow\r\n\r\n%% Unscramble\r\n% \r\n% <<unscramble.png>>\r\n% \r\n% The two buttons at the lower left unscramble the cube.\r\n% The |<=| button generates a rotation in the direction opposite the\r\n% rotation at the top of the stack.  This acts like a backspace.\r\n% The |<==| toggle repeatedly backspaces until the stack is empty.\r\n% This is the smart way to \"solve\" the puzzle REPLACE_WITH_DASH_DASH remember how it was\r\n% scrambled.\r\n%\r\n% Let's unscramble the cube and get back to |Q0|.\r\n%\r\n\r\n    show_undo(3,3)\r\n    snapnow\r\n    \r\n%% Appearance\r\n% The buttons in the left-hand group control the appearance\r\n% of the simulator.\r\n%\r\n% <<lhs.png>>\r\n\r\n%%\r\n% *width*\r\n%\r\n% The vertices of the basic unit cubelet, |qzero|, are the eight\r\n% combinations of +1 and -1, so the half-width of |qzero| is one.\r\n% The twenty-seven cubelets in |Q0| are scaled by this |width| parameter\r\n% to produce gaps between the individual cubelets.\r\n\r\n    show_width(1,3)\r\n    snapnow\r\n    \r\n%% \r\n% *nstep*\r\n%\r\n% The number of fractional rotations in\r\n% a quarter turn controls |Qube's| speed.\r\n\r\n%% \r\n% *type*\r\n%\r\n% The cubelet centers are the points |[x,y,z]| where |x|, |y| and |z|\r\n% are combinations of -2, 0 and 2.  The cubelet type is the number of\r\n% nonzeros in coordinates of its center, |nnz([x,y,z])|.\r\n%\r\n%  * 0: center\r\n%  * 1: face\r\n%  * 2: edge\r\n%  * 3: corner\r\n\r\n    show_types\r\n    snapnow\r\n\r\n%%\r\n% *color*\r\n%\r\n% An alternative to the traditional Rubik's colors\r\n% made from the MATLAB axes color order.\r\n\r\n    show_color(1,3)\r\n    snapnow\r\n\r\n%%\r\n% *mouse*\r\n%\r\n% This button turns on Handle Graphics |rotate3d|.  You can then\r\n% use your mouse to rotate the viewpoint.  The visual effect is \r\n% the same as rotating the entire cube.\r\n\r\n%% Actions\r\n% The buttons in the right-hand group initiate computations.\r\n% Other tools may be added.\r\n%\r\n% <<rhs.png>>\r\n\r\n%% \r\n% *solve*\r\n%\r\n% Experimental solver.\r\n% Greedy algorithm to minimize the\r\n% sum of SVDs of the difference between the cubelets in the\r\n% current cube and cubelets in Q0.  Also known as the nuclear norm.\r\n% It turns out that this solver does not work very well.\r\n\r\n%%\r\n% *period*\r\n%\r\n% Number of repetitions to return to Q0. A fundamental notion in group\r\n% theory.\r\n\r\n%%\r\n% *reset*\r\n%\r\n% Reinitialize without restarting.\r\n\r\n%%\r\n%\r\n% *restart*\r\n%\r\n% Complete restart.\r\n\r\n%%\r\n% *Q0*\r\n%\r\n% Restore |Q0|.\r\n\r\n%% Upper left-hand side\r\n%\r\n% <<upper_lhs.png>>\r\n\r\n%%\r\n% *score*\r\n%\r\n% Currently, the nuclear norm distance to Q0.  Need something more\r\n% sensitive to Rubik's cube patterns.\r\n\r\n%% \r\n% *count*\r\n%\r\n% Number of rotations.  Hence, the period.\r\n\r\n%%\r\n% *post*\r\n%\r\n% Most recent rotation.\r\n\r\n%% Upper right-hand side\r\n%\r\n% <<upper_rhs.png>>\r\n%\r\n\r\n%%\r\n% *help*\r\n%\r\n% |helpwin Qube|\r\n\r\n%%\r\n% *info*\r\n%\r\n% Pointer to this blog post.\r\n\r\n%% Software\r\n% The source code for |Qube| is available from this link:\r\n% <https:\/\/blogs.mathworks.com\/cleve\/files\/Qube_osf.m Qube_osf.m>.\r\n% The |osf|, _one single file_,  format is a self-extracting archive\r\n% that expands into a directory of individual functions.\r\n\r\n\r\n##### SOURCE END ##### e088f81bace24fbc898464d501445288\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img src=\"https:\/\/blogs.mathworks.com\/cleve\/files\/Qube.png\" class=\"img-responsive attachment-post-thumbnail size-post-thumbnail wp-post-image\" alt=\"\" decoding=\"async\" loading=\"lazy\" \/><\/div><!--introduction--><p>This blog post describes <tt>Qube<\/tt>, my Rubik's Cube simulator. Source code for <tt>Qube<\/tt> is now available in <i>one single file<\/i> from this link: <a href=\"https:\/\/blogs.mathworks.com\/cleve\/files\/Qube_osf.m\">Qube_osf.m<\/a>. I will also submit the code to the MATLAB Central File Exchange. As usual, I welcome any feedback.... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/cleve\/2022\/04\/12\/digital-simulation-of-rubiks-cube-with-qube\/\">read more >><\/a><\/p>","protected":false},"author":78,"featured_media":8540,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[32,5,23,6,37,26,39,30],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts\/8507"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/users\/78"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/comments?post=8507"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts\/8507\/revisions"}],"predecessor-version":[{"id":8510,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/posts\/8507\/revisions\/8510"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/media\/8540"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/media?parent=8507"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/categories?post=8507"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/cleve\/wp-json\/wp\/v2\/tags?post=8507"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}