{"id":17026703,"url":"https://github.com/chenanton/ai-rubiks-cube-solver","last_synced_at":"2025-10-10T08:36:08.467Z","repository":{"id":92108422,"uuid":"282062498","full_name":"chenanton/ai-rubiks-cube-solver","owner":"chenanton","description":"A program which generates a sequence of cube rotations learned from a deep neural network, solving a scrambled Rubik's Cube.","archived":false,"fork":false,"pushed_at":"2020-08-31T15:10:12.000Z","size":157233,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-12T11:48:34.781Z","etag":null,"topics":["data-generator","keras","machine-learning","matplotlib-pyplot","neural-network","python","rubiks-cube","rubiks-cube-solver","tensorflow2"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chenanton.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-07-23T21:48:54.000Z","updated_at":"2025-03-10T23:06:56.000Z","dependencies_parsed_at":"2023-03-13T17:34:10.400Z","dependency_job_id":null,"html_url":"https://github.com/chenanton/ai-rubiks-cube-solver","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chenanton/ai-rubiks-cube-solver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chenanton%2Fai-rubiks-cube-solver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chenanton%2Fai-rubiks-cube-solver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chenanton%2Fai-rubiks-cube-solver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chenanton%2Fai-rubiks-cube-solver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chenanton","download_url":"https://codeload.github.com/chenanton/ai-rubiks-cube-solver/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chenanton%2Fai-rubiks-cube-solver/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279003277,"owners_count":26083555,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-generator","keras","machine-learning","matplotlib-pyplot","neural-network","python","rubiks-cube","rubiks-cube-solver","tensorflow2"],"created_at":"2024-10-14T07:34:10.830Z","updated_at":"2025-10-10T08:36:08.462Z","avatar_url":"https://github.com/chenanton.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- PROJECT LOGO --\u003e\n\u003cbr /\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/azychen/rubiks-cube-solver\"\u003e\n        \u003cimg src=\"assets/animations/spinning_cube.gif\" alt=\"Logo\" width=\"180\" \u003e\n    \u003c/a\u003e\n    \u003ch2 align=\"center\" \u003eAI Rubik's Cube Solver\u003c/h2\u003e\n    \u003cbr /\u003e\n  \u003cp align=\"center\"\u003e\n    A program which generates a sequence of machine-learned cube turns, solving a scrambled Rubik's Cube.\n    \u003cbr /\u003e\n  \u003c/p\u003e\n\u003c/p\u003e\n    \u003cbr /\u003e\n\n![GIF](assets/animations/solve0.gif)\n\n\u003c!-- TABLE OF CONTENTS --\u003e\n\n## Table of Contents\n\n* [Background](#background)\n* [Outline](#outline)\n* [Getting Started](#getting-started)\n* [Roadmap](#roadmap)\n  + [Cube Model](#cube-model)\n  + [Scrambling](#scrambling)\n  + [Generating Data](#generating-data)\n  + [Training Model](#training-model)\n* [Results and Discussion](#results-and-discussion)\n\n\u003c!-- * [Conclusion](#conclusion) --\u003e\n\u003c!-- * [Contact](#contact) --\u003e\n\u003c!-- * [Acknowledgements](#acknowledgements) --\u003e\n\n\u003c!-- BACKGROUND --\u003e\n\n## Background\n\n\u003c!-- [![Product Name Screen Shot][product-screenshot]](https://example.com) --\u003e\n\nWith more than **43 quintillion unique combinations**, a scrambled Rubik's Cube seems impossible to solve. Yet with a simple guide, anyone can learn how to solve it. My first solve attempt took me 30 minutes, and within a week, that time was down to 5 minutes. \n\nWhat's even more impressive are \"speedcubers\" who can solve a scrambled cube in [less than 10 seconds!](https://www.youtube.com/watch?v=NevGDFBfQGw) They use techniques such as [CFOP](https://www.speedsolving.com/wiki/index.php/CFOP_method), [Roux](https://www.speedsolving.com/wiki/index.php/Roux_method), or [ZZ](https://www.speedsolving.com/wiki/index.php/ZZ_method), which work by memorizing many combinations of turns (known as algorithms) and when to use them.\n\nHowever, we're not here to memorize a bunch of algorithms - **we want a machine to learn how to solve it.** Can we harness the power of machine learning to solve a Rubik's Cube?\n\n\u003c!-- OUTLINE --\u003e\n\n## Outline\n\n* Written in [**Python**](https://www.python.org/).\n* Neural network implementation with [**TensorFlow**](https://www.tensorflow.org/).\n* Tensor operations with [**NumPy**](https://numpy.org/).\n* GUI with [**Matplotlib**](https://matplotlib.org/) and [**MagicCube**](https://github.com/davidwhogg/MagicCube).\n* Unit testing  with [**UnitTest**](https://docs.python.org/3/library/unittest.html).\n\n\u003c!-- DEMO --\u003e\n\n\u003c!-- ## Demo --\u003e\n\n\u003c!-- Getting Started --\u003e\n\n## Getting Started\n\n### Install dependencies\n\n* Python: [download link](https://www.python.org/downloads/)\n\n``` sh\npip install tensorflow matplotlib numpy\n```\n\n### Clone repository\n\n``` sh\ngit clone https://github.com/azychen/rubiks-cube-solver\n```\n\n### Run program\n\n``` sh\npython -u main.py\n```\n\n\u003c!-- ROADMAP --\u003e\n\n## Roadmap\n\n\u003c!-- CUBE MODEL --\u003e\n\n### Cube Model\n\nThe stickers on the cube are represented by a 6 x 3 x 3 tensor, representing the six sides with 3 rows and 3 columns of stickers. Each sticker is represented as an integer from 0 to 5. To rotate a face clockwise, the corresponding side's 3 x 3 face must be rotated clockwise. Additionally, the 12 stickers on the 4 adjacent sides must also be moved to the correct position. This applies similarly to a counter-clockwise rotation. Here's an example:\n\n``` python\n# Example: class method to rotate bottom face clockwise (D)\ndef rotateD(self):\n        self.stickers[0] = np.rot90(self.stickers[0], axes=(1, 0))\n        self.stickers[[4, 3, 5, 2], 2] = self.stickers[[3, 5, 2, 4], 2]\n```\n\n\u003c!-- SCRAMBLING --\u003e\n\n### Scrambling\n\nAfter implementing clockwise, double, and counter-clockwise rotations for all 6 sides (18 moves total), we can start scrambling the cube (and eventually generate data). As any scrambled cube can be solved within [20 moves](https://www.cube20.org/#:~:text=New%20results%3A%20God's%20Number%20is,requires%20more%20than%20twenty%20moves.\u0026text=At%20long%20last%2C%20God's%20Number%20has%20been%20shown%20to%20be%2020. \"God's Number\"), we will scramble the cube with no more than 25 moves. More specifically, moves must not cancel each other out (e.g. a clockwise rotation followed immediately by a counter-clockwise rotation on the same face), and must be optimal (e.g. 4 clockwise rotations of the same face does not change anything).\n\n``` python\n# List of turns, with the letter representing the face turned clockwise\n# 2 marks a double rotation\n# Prime (') marks a counter-clockwise rotation\nturns = [\"D\", \"D2\", \"D'\", \"U\", \"U2\", \"U'\", \"F\", \"F2\", \"F'\",\n         \"B\", \"B2\", \"B'\", \"L\", \"L2\", \"L'\", \"R\", \"R2\", \"R'\"]\n```\n\n\u003c!-- GENERATING DATA --\u003e\n\n### Generating Data\n\nIn order to find unique solutions to generate data and train a neural network, I use [Herbert Kociemba's two-phase optimal solving algorithm](https://en.wikipedia.org/wiki/Optimal_solutions_for_Rubik%27s_Cube#Kociemba's_algorithm \"Kociemba's Algorithm\") to generate solutions for the scrambled cubes. Conveniently, [tcbegley's implementation of Kociemba's Algorithm](https://github.com/tcbegley/cube-solver) works very well to get solutions. For each scramble, I save the first move generated. This means with every scramble we generate, we also have moves to solve it! \n\n\u003c!-- TRAINING MODEL --\u003e\n\n### Training Model\n\nWith access to any scramble's respective solution, we can train a model, where the stickers' location on a cube maps to the moves most likely to solve it. \n\nI use a fully-connected deep neural network, with the Adam optimizer for backpropagation and parameter updating, along with a sparse categorical cross-entropy loss. Here's a look at the structure:\n\n\u003cimg src=\"assets/images/nn-architecture.png\" alt=\"Model Architecture\" width=\"300\"/\u003e\n\u003c!-- \u003cp align=\"center\"\u003e\n\n    \u003ca href=\"https://github.com/azychen/rubiks-cube-solver\"\u003e\n      \u003cimg src=\"assets/images/nn-architecture.png\" alt=\"Model Architecture\" width=\"320\" \u003e\n\n  \u003c/a\u003e\n\u003c/p\u003e --\u003e\n\nAnd here's the implementation with the Keras sequential model:\n\n``` python\n# Create layers\nmodel = keras.Sequential([\n    keras.layers.Input(shape=54),\n    keras.layers.Dense(units=2048, activation=\"relu\", name=\"dense0\"),\n    keras.layers.Dense(units=512, activation=\"relu\", name=\"dense1\"),\n    keras.layers.Dense(units=128, activation=\"relu\", name=\"dense2\"),\n    keras.layers.Dense(units=32, activation=\"relu\", name=\"dense3\"),\n])\n\n# Compile model\nmodel.compile(loss=\"sparse_categorical_crossentropy\",\n              optimizer=\"adam\", metrics=[\"accuracy\"])\n```\n\n## Results and Discussion\n\nAfter training on over 8 million training examples, the network has a validation accuracy of approximately 70%. In other words, the model can predict the next move in the solution a considerable amount of the time. In practice, this means that the model is incredibly accuracy when it comes to predicting solution sequences for scrambles less than 6-7 moves long. However, as scramble length increases beyond this, the model struggles to find accurate moves to solve the cube.\n\nTo improve results, it may suffice to simply generate more data to be fed into the model. \n\n\u003c!-- \n\n## Conclusion --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchenanton%2Fai-rubiks-cube-solver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchenanton%2Fai-rubiks-cube-solver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchenanton%2Fai-rubiks-cube-solver/lists"}