Browse Source

Initial commit

master
Daniel Walton 2 years ago
parent
commit
00ed991ac9
41 changed files with 226643 additions and 0 deletions
  1. +8
    -0
      .gitignore
  2. +55
    -0
      README.md
  3. +47
    -0
      TODO.txt
  4. +17
    -0
      misc/NOTES-2x2x2.txt
  5. +201
    -0
      misc/NOTES-4x4x4.txt
  6. +185
    -0
      misc/NOTES-5x5x5.txt
  7. +31
    -0
      misc/NOTES-6x6x6.txt
  8. +10
    -0
      misc/NOTES-7x7x7.txt
  9. +85
    -0
      misc/TODO.txt
  10. +2507
    -0
      rubikscubennnsolver/LookupTable.py
  11. +178
    -0
      rubikscubennnsolver/RubiksCube222.py
  12. +29
    -0
      rubikscubennnsolver/RubiksCube333.py
  13. +2700
    -0
      rubikscubennnsolver/RubiksCube444.py
  14. +1728
    -0
      rubikscubennnsolver/RubiksCube555.py
  15. +760
    -0
      rubikscubennnsolver/RubiksCube666.py
  16. +1291
    -0
      rubikscubennnsolver/RubiksCube777.py
  17. +450
    -0
      rubikscubennnsolver/RubiksCubeNNN.py
  18. +619
    -0
      rubikscubennnsolver/RubiksSide.py
  19. +4545
    -0
      rubikscubennnsolver/__init__.py
  20. +1134
    -0
      rubikscubennnsolver/rotate_xxx.py
  21. +15
    -0
      setup.py
  22. +207
    -0
      usr/bin/rubiks-cube-solver.py
  23. +258
    -0
      utils/binary-search.c
  24. +98
    -0
      utils/binary-search.py
  25. +151
    -0
      utils/build-test-cases.py
  26. +42
    -0
      utils/convert-to-binary.py
  27. +18
    -0
      utils/find-next-prime-number.py
  28. +23
    -0
      utils/fix_foo.py
  29. +27
    -0
      utils/hash_stats.py
  30. +105
    -0
      utils/make-5x5x5-step10-prune-table-LFRB.py
  31. +105
    -0
      utils/make-5x5x5-step10-prune-table-UFDB.py
  32. +12
    -0
      utils/print-solved.py
  33. +11
    -0
      utils/prune-table-step-count-only.py
  34. +107
    -0
      utils/rotate-printer.py
  35. +207540
    -0
      utils/states-to-find-lookup-table-5x5x5-step10-UD-centers-stage.txt
  36. +159
    -0
      utils/test.py
  37. +331
    -0
      utils/test_cubes.json
  38. +831
    -0
      utils/test_cubes.json.huge
  39. BIN
      www/Arrow-Next.png
  40. BIN
      www/Arrow-Prev.png
  41. +23
    -0
      www/solution.js

+ 8
- 0
.gitignore View File

@@ -87,3 +87,11 @@ ENV/

# Rope project settings
.ropeproject

lookup-table-*.txt
*.swp
cache
lookup-table-*-deep*
not_used
binary-search
*.hash

+ 55
- 0
README.md View File

@@ -0,0 +1,55 @@
# rubiks-cube-NxNxN-solver

## Overview
This is a work in progress...here is what works so far:
* 2x2x2 works
* 3x3x3 works via the kociemba solver
* 4x4x4 works, average solution is 65 moves
* 5x5x5 works, average solution is 119 moves
* 6x6x6 works, average solution is 214 moves
* 7x7x7 works, average solution is 304 moves
* NxNxN even cubes, am testing with a 14x14x14, not working yet
* NxNxN odd cubes, am testing with a 15x15x15, not working yet

All cubes 4x4x4 and larger follow the same basic approach:
* Solve centers
* Pair edges
* Solve as 3x3x3

## Install

### Install 3x3x3 solver
The kociemba solver is required to solve the larger cubes that have been
reduced to 3x3x3.

```
$ git clone https://github.com/dwalton76/kociemba.git
$ cd ~/kociemba/kociemba/ckociemba/
$ make
$ sudo make install
```

### Install the rubikscubennnsolver python module
```
$ git clone https://github.com/dwalton76/rubiks-cube-NxNxN-solver.git
$ cd rubiks-cube-NxNxN-solver
$ sudo python2 setup.py install
$ gunzip lookup-table*.gz
```

## Usage
Run rubiks-cube-solver.py where --state is your cube state in kociemba
order (URFDLB). You must run rubiks-cube-solver.py from the directory that
holds your lookup-table\*.txt files

Example:
```
$ cd ~/rubiks-cube-NxNxN-solver
$ ./usr/bin/rubiks-cube-solver.py --state LFBDUFLDBUBBFDFBLDLFRDFRRURFDFDLULUDLBLUUDRDUDUBBFFRBDFRRRRRRRLFBLLRDLDFBUBLFBLRLURUUBLBDUFUUFBD
```

## History
One of my hobbies is building Lego Mindstorms robots that can solve rubiks cubes. I was able to find solvers for 2x2x2, 3x3x3, 4x4x4 and 5x5x5 but I couldn't find a solver for anything larger than that :( The solvers that I did find for 4x4x4 and 5x5x5 took quite a bit of RAM (several gigs) but I wanted to be able to run the solver on a Lego Mindstorms EV3 which is 300Mhz and 64M of RAM. So I decided to write my own solver and here we are :)

Here is the thread on speedsolving.com where I first posted looking for solvers. I ended up posting updates to this thread as my solver evolved:
https://www.speedsolving.com/forum/threads/5x5x5-6x6x6-7x7x7-or-nxnxn-solvers.63592/

+ 47
- 0
TODO.txt View File

@@ -0,0 +1,47 @@

DONE - remove max_depth everywhere
DONE - remove prune_table boolean? I don't think this is used
- build these deeper and convert to .bin file using pack()
- 4x4x4-ULFRBD-centers-stage - currently 6-deep
- 5x5x5-UD-centers-stage - currently 6-deep
- 5x5x5-LR-centers-stage would be 165 million so uses IDA...could probably build all 165million via .bin and avoid IDA here
- 6x6x6-UD-oblique-edge-pairing - currently 6-deep
- 6x6x6-LR-oblique-edge-pairing would be 165 million so uses IDA...could probably build all 165million via .bin and avoid IDA here


DONE - build 5x5x5-ULFRBD-centers-solve deeper? I built a much better prune table
- build 6x6x6-LFRB-solve-inner-x-center-and-oblique-edges deeper? Need a clever way to compress it




solutions.html
DONE - need an arrow that loads the next step of instructions
- highlight the face/rows that you should be turning
- have a play/pause button so that it auto increments every 5s


444 solver
- look into the 52 moves tables xyzzy is using


NNN solver
- work on centers for 14x14x14


DONE - rotate_xxx() can we compress the lists down to a few lists additions?
same for state_functions


4x4x4 Tsai...could we combine first two phases?
If you solved LR from the start that table would have 24!/(4!*4!*16!) or 51482970
If you stage UD and FB from the start that table would be 24!/(8!*8!*8!) or 9465511770
If you solved LR and stage UD and FB from the start that table would be 24!/(4!*4!*8!*8!) or 662585823900
The orient_table has 2704156

The main table would be 24!/(4!*4!*8!*8!) * 2704156 or 1791735431214128400
51482970/1791735431214128400 is 0.0000000000287336 so that would be very very slow
9465511770/1791735431214128400 is 0.0000000052828736 so that might be doable but this is borderline
but requires you to build a prune table that is 9.4 billion entries
662585823900/1791735431214128400 is 0.0000003698011505 so that would work
but requires you to build a prune table that is 662 billion entries

+ 17
- 0
misc/NOTES-2x2x2.txt View File

@@ -0,0 +1,17 @@

Using solver from stackoverflow
===============================
2x2x2 min solution 6 steps
2x2x2 max solution 10 steps
2x2x2 avg solution 8 steps

5.06user 0.08system 0:05.26elapsed 97%CPU (0avgtext+0avgdata 12336maxresident)k


Using lookup table
==================
2x2x2 min solution 6 steps
2x2x2 max solution 10 steps
2x2x2 avg solution 8 steps

0.08user 0.00system 0:00.08elapsed 100%CPU (0avgtext+0avgdata 12432maxresident)k

+ 201
- 0
misc/NOTES-4x4x4.txt View File

@@ -0,0 +1,201 @@
These are the numbers from running --test against the 4x4x4 test cases

4x4x4 original numbers
======================
4x4x4 min solution 172 steps
4x4x4 max solution 415 steps
4x4x4 avg solution 285 steps
10.496s to test all 50


Look at unpaired edges and do the one that solves
the most edges in the least amount of moves
=================================================
4x4x4 min solution 132 steps
4x4x4 max solution 335 steps
4x4x4 avg solution 228 steps


OLL/PLL parity avoided...exit on first parity free center setup
===============================================================
4x4x4 min solution 120 steps
4x4x4 max solution 177 steps
4x4x4 avg solution 148 steps
real 1m0.480s
user 0m53.284s
sys 0m1.980s


Simplified some code to make troubleshooting easier
and to run faster. Without using a centers lookup table.
===================================================
4x4x4 min solution 138 steps
4x4x4 max solution 190 steps
4x4x4 avg solution 153 steps

10.78user 0.23system 0:11.55elapsed 95%CPU (0avgtext+0avgdata 15568maxresident)k


With center lookup table with a depth of 5
===================================================
4x4x4 min solution 124 steps
4x4x4 max solution 190 steps
4x4x4 avg solution 153 steps

12.66user 2.25system 0:15.34elapsed 97%CPU (0avgtext+0avgdata 388084maxresident)k


With center lookup table with a depth of 6
===================================================
4x4x4 min solution 126 steps
4x4x4 max solution 172 steps
4x4x4 avg solution 149 steps

60.45user 32.45system 1:39.96elapsed 92%CPU (0avgtext+0avgdata 6016192maxresident)k


With binary search through lookup table instead of loading into dictionary
This went from 1m 39s to 15s!!!
==========================================================================
4x4x4 min solution 126 steps
4x4x4 max solution 172 steps
4x4x4 avg solution 149 steps

14.53user 0.40system 0:15.53elapsed 96%CPU (0avgtext+0avgdata 15684maxresident)k


With lookup tables:
- lookup-table-4x4x4-centers-UD.txt
- lookup-table-4x4x4-centers-LFRB.txt
==========================================================================
4x4x4 min solution 85 steps
4x4x4 max solution 113 steps
4x4x4 avg solution 97 steps

9.51user 2.31system 0:12.42elapsed 95%CPU (0avgtext+0avgdata 16692maxresident)k


With OLL and PLL detection working
- group_edges now solves with each of the 12 edges as the first edge to solve
and keeps the one with the lowest score. This makes it a bit slower though.
==========================================================================
4x4x4 min solution 83 steps
4x4x4 max solution 110 steps
4x4x4 avg solution 93 steps

40s


Added pair_six_444_edges()
==========================================================================
4x4x4 min solution 73 steps
4x4x4 max solution 94 steps
4x4x4 avg solution 83 steps

4.43user 0.06system 0:04.59elapsed 97%CPU (0avgtext+0avgdata 20436maxresident)k


Added
- lookup-table-4x4x4-edges-slice-backward.txt
- lookup-table-4x4x4-edges-slice-forward.txt
=============================================
4x4x4 min solution 66 steps
4x4x4 max solution 90 steps
4x4x4 avg solution 75 steps

8.55user 0.34system 0:09.02elapsed 98%CPU (0avgtext+0avgdata 22132maxresident)k


Added pair_four_444_edges()
===========================
4x4x4 min solution 65 steps
4x4x4 max solution 88 steps
4x4x4 avg solution 74 steps


Added pair_last_six_edges_444()
===============================
4x4x4 min solution 63 steps
4x4x4 max solution 88 steps
4x4x4 avg solution 70 steps


I forget what I changed :(
==========================
4x4x4 min solution 61 steps
4x4x4 max solution 90 steps
4x4x4 avg solution 68.0 steps
4x4x4 avg centers solution 19.0 steps
4x4x4 avg edges solution 27.0 steps

7.55user 0.28system 0:08.19elapsed 95%CPU (0avgtext+0avgdata 12784maxresident)k
23576inputs+0outputs (0major+65360minor)pagefaults 0swaps


Changed state from dict to list
===============================
No change in move count but it does run a bit faster
6.92user 0.22system 0:07.26elapsed 98%CPU (0avgtext+0avgdata 12712maxresident)k


Sometimes accept a PLL edge pairing solution
============================================
The max solution drop from 90 to 79...solving PLL takes 12 moves so if all
effecient edge pairing solutions lead to PLL just accept it and solve the
PLL.

4x4x4 min solution 59 steps
4x4x4 max solution 79 steps
4x4x4 avg solution 67.0 steps
4x4x4 avg centers solution 19.0 steps
4x4x4 avg edges solution 27.0 steps


Consider number of wings paired by solution to solve centers
============================================================
4x4x4 min solution 59 steps
4x4x4 max solution 75 steps
4x4x4 avg solution 66.0 steps
4x4x4 avg centers solution 18.0 steps
4x4x4 avg edges solution 27.0 steps


Use recursion for edge pairing and 4x4x4-edges
==============================================
The 4x4x4-edges table was only 9-moves deep here so this was just the beginning

4x4x4 min solution 59 steps (FUULURFFRLRBDDDULUDFLFBBFUURRRUBLBLBDLUBDBULDDRDFLFBBRDBFDBLRBLDULUFFRLRDLDBBRLRUFFRUBFDUDFRLFRU)
4x4x4 max solution 76 steps (FUBLRFFUBBBFFFRFURFFDDDRFRDDDRFLRDBRBRLFLBULRBUBUURRDUUDLLLRUURBDBLDURLDDRFFBULBULLLDFUFBBDLDUBL)
4x4x4 avg solution 66.0 steps
4x4x4 avg centers solution 19.0 steps
4x4x4 avg edges solution 25.0 steps

13.91user 0.70system 0:14.83elapsed 98%CPU (0avgtext+0avgdata 16640maxresident)


Replaced all copy.copy with list slices...small speed improvement
=================================================================
13.59user 0.74system 0:14.57elapsed 98%CPU (0avgtext+0avgdata 16068maxresident)k


Replaced all range() with xrange()
==================================
13.41user 0.62system 0:14.26elapsed 98%CPU (0avgtext+0avgdata 16076maxresident)k



2017-08-02
==========
4x4x4 avg centers solution 19.0 steps
4x4x4 avg edges solution 25.0 steps
4x4x4 avg solution 65.0 steps
4x4x4 min solution 59 steps (FUULURFFRLRBDDDULUDFLFBBFUURRRUBLBLBDLUBDBULDDRDFLFBBRDBFDBLRBLDULUFFRLRDLDBBRLRUFFRUBFDUDFRLFRU)
4x4x4 max solution 75 steps (FLDRFFBLFDLRURUUFBUBLRUFUDUBULLFRUBLRRRUDFDFDUBBRRDLUFDDRFBDDFBDDDRFDLUDBLRBLFFBUFBLLLURRBBLRULB)

13.22user 0.50system 0:13.98elapsed 98%CPU (0avgtext+0avgdata 15672maxresident)k


unroll 4x4x4 state loops
========================
11.62user 0.47system 0:12.28elapsed 98%CPU (0avgtext+0avgdata 15740maxresident)k


+ 185
- 0
misc/NOTES-5x5x5.txt View File

@@ -0,0 +1,185 @@

********************
Main 5x5x5 test cube
********************

Baseline
========
190 steps to solve centers
175 steps to group edges
19 steps to solve 3x3x3
384 steps total




*************
50 Test Cubes
*************

Initial solve for all 50 5x5x5 test cubes...this took some doing
================================================================
5x5x5 min solution 327 steps
5x5x5 max solution 453 steps
5x5x5 avg solution 387 steps
1m 3s


Lookup tables for centers
edge pairing can do 3 on slice forward and 3 on slice back
==========================================================
5x5x5 min solution 107 steps
5x5x5 max solution 169 steps
5x5x5 avg solution 130 steps
Takes a while...10m or so


Use 4x4x4 to pair outer edges first
This takes more moves than the old way but the code is a
million times cleaner and it runs in 1min instead of 10min
==========================================================
5x5x5 min solution 124 steps
5x5x5 max solution 190 steps
5x5x5 avg solution 146 steps

59.08user 3.60system 1:02.79elapsed 99%CPU (0avgtext+0avgdata 13604maxresident)k


More 5x5x5 edge pairing cleanup
===============================
5x5x5 min solution 121 steps
5x5x5 max solution 172 steps
5x5x5 avg solution 141.0 steps
5x5x5 avg centers solution 36.0 steps
5x5x5 avg edges solution 84.0 steps

44.12user 3.97system 0:59.96elapsed 80%CPU (0avgtext+0avgdata 13264maxresident)k


Changed state from dict to list
===============================
No change in move count but it does run 6s faster
38.03user 3.12system 0:41.25elapsed 99%CPU (0avgtext+0avgdata 12836maxresident)k


Use init_wing_to_pair approach...saves 6 steps but doubles the time
===================================================================
5x5x5 min solution 119 steps
5x5x5 max solution 153 steps
5x5x5 avg solution 135.0 steps
5x5x5 avg centers solution 36.0 steps
5x5x5 avg edges solution 78.0 steps

81.05user 4.18system 1:25.34elapsed 99%CPU (0avgtext+0avgdata 12972maxresident)k


After lots of misc IDA fixes
============================
5x5x5 min solution 113 steps
5x5x5 max solution 177 steps
5x5x5 avg solution 141.0 steps
5x5x5 avg centers solution 40.0 steps
5x5x5 avg edges solution 79.0 steps


After some 4x4x4 edge pairing fixes
===================================
The max solution case went from 177 to 157!!!

5x5x5 min solution 114 steps
5x5x5 max solution 157 steps
5x5x5 avg solution 135.0 steps
5x5x5 avg centers solution 40.0 steps
5x5x5 avg edges solution 73.0 steps


Use recursion for edge pairing and 4x4x4-edges
==============================================
The 4x4x4-edges table was only 9-moves deep here so this was just the beginning

5x5x5 min solution 118 steps
5x5x5 max solution 163 steps
5x5x5 avg solution 141.0 steps
5x5x5 avg centers solution 40.0 steps
5x5x5 avg edges solution 80.0 steps


Added NoIDASolution to dynamically 'solve' prune
table when the IDA search it taking too long. This
takes longer to run but chops 3 moves from centers
solution.
==================================================
5x5x5 min solution 119 steps (LFUUFUBRBDRBUUFLLURLBRBFURFRLUDBBFRBDRURUBDDDDBDBULDURFFFFRFBBFUDBRRLLRLULRUBLUFRFDFUFLDFLRLLDDDFLRBFBDFDBDDUURBLFLLRLURBDDUBLRFUDFULUDURBFBLLRDBLBFDR)
5x5x5 max solution 163 steps (LLBLDDFUBBUDUFDLDRRFUUDRRULBLBLLBUFDURURDBLDBDRFULRRFDBRRLLFUDFURULBRFFRFFLLBUDBFFDFFDRDRRRBLDBDLFLDBBBBFUULUDLFLDLURFURRBLRURDRUUUBBFBURBFBDDBLFFDLUF)
5x5x5 avg solution 139.0 steps
5x5x5 avg centers solution 37.0 steps
5x5x5 avg edges solution 81.0 steps


Edge pairing improvements
- no longer use 4x4x4 first
- recurse through all edge combos
- edge prune estimate of 3
==================================================
5x5x5 min solution 101 steps (RDBFBUDDLRDRUULLFFDDFBBDDLLUDLRUUBRRLRBBBRUDBBDDFRUURRFDRLRULBFLUFLDFLFFLDDLRBBLLFDLBFBDBFFRFFRRFRBBBLRBRRLDUFURLLDUBFBUFLLUUUDULDUBFDBDUBRFRURUFUUFLD)
5x5x5 max solution 133 steps (URUBFUUFRDFFUUFLRDBLLBDDDLUULRDLDUBDLRBBLFLBRBFUUBBRBFFUDLFLLBFUFUDRLBFUBBURRLLRUFRDUFFDFRFUBRBBDRFRFLLFURLLFBRBLUDRDDRRDRRFDUDLFLDLUUDUDBRBBBRBDDLDFL)
5x5x5 avg solution 119.0 steps
5x5x5 avg centers solution 36.0 steps
5x5x5 avg edges solution 62.0 steps


- edge prune estimate of 2.5
==================================================
# It is 4 moves shorter but takes much longer to run
5x5x5 min solution 101 steps (RDBFBUDDLRDRUULLFFDDFBBDDLLUDLRUUBRRLRBBBRUDBBDDFRUURRFDRLRULBFLUFLDFLFFLDDLRBBLLFDLBFBDBFFRFFRRFRBBBLRBRRLDUFURLLDUBFBUFLLUUUDULDUBFDBDUBRFRURUFUUFLD)
5x5x5 max solution 132 steps (URUBFUUFRDFFUUFLRDBLLBDDDLUULRDLDUBDLRBBLFLBRBFUUBBRBFFUDLFLLBFUFUDRLBFUBBURRLLRUFRDUFFDFRFUBRBBDRFRFLLFURLLFBRBLUDRDDRRDRRFDUDLFLDLUUDUDBRBBBRBDDLDFL)
5x5x5 avg solution 115.0 steps
5x5x5 avg centers solution 36.0 steps
5x5x5 avg edges solution 58.0 steps


2017-08-02
==========
5x5x5 avg centers solution 36.0 steps
5x5x5 avg edges solution 62.0 steps
5x5x5 avg solution 119.0 steps
5x5x5 min solution 101 steps (RDBFBUDDLRDRUULLFFDDFBBDDLLUDLRUUBRRLRBBBRUDBBDDFRUURRFDRLRULBFLUFLDFLFFLDDLRBBLLFDLBFBDBFFRFFRRFRBBBLRBRRLDUFURLLDUBFBUFLLUUUDULDUBFDBDUBRFRURUFUUFLD)
5x5x5 max solution 133 steps (URUBFUUFRDFFUUFLRDBLLBDDDLUULRDLDUBDLRBBLFLBRBFUUBBRBFFUDLFLLBFUFUDRLBFUBBURRLLRUFRDUFFDFRFUBRBBDRFRFLLFURLLFBRBLUDRDDRRDRRFDUDLFLDLUUDUDBRBBBRBDDLDFL)

432.35user 10.22system 7:34.63elapsed 97%CPU (0avgtext+0avgdata 118340maxresident)k


unroll 5x5x5 state loops
========================
401.68user 9.84system 7:08.33elapsed 96%CPU (0avgtext+0avgdata 118356maxresident)k



WIP on switching to hash...why is this slower?
==============================================
299.76user 25.02system 8:35.15elapsed 63%CPU (0avgtext+0avgdata 96700maxresident)k


with edge estimate 3.5 we get
=============================
5x5x5 avg centers solution 36.0 steps
5x5x5 avg edges solution 68.0 steps
5x5x5 avg solution 125.0 steps
5x5x5 min solution 101 steps (FFRUUUDRFBFLUUURRFLLBBFFRFBBURFURUBFBRFBLUURBRFLFLULRLURBBDDLFFUURDRFDFUBDDDRDRBFRFLLUDDBDUFBLRRBDDBLFDFLRBLRBRLLRFDLDFDFLLULBLUDUDUUBULLBDBUDDBLDBRRD)
5x5x5 max solution 141 steps (BLFUFDBFLFURULRBURFLDURLRDUBLRBLLLDLDRLFUFFURLULBBBRDBFBDDLUDRFUBBFBDFFRBRFDDUFULRRBLRBDBUDBUDRDRFLLRFRULDRDURBDLFLRBBDLBBFDLUFDFUFFUUBLUBLDURFRDUDUFR)

175.40user 18.62system 5:25.17elapsed 59%CPU (0avgtext+0avgdata 96420maxresident)k


with edge estimate 4.0 we get
=============================
5x5x5 avg centers solution 36.0 steps
5x5x5 avg edges solution 71.0 steps
5x5x5 avg solution 128.0 steps
5x5x5 min solution 101 steps (FFRUUUDRFBFLUUURRFLLBBFFRFBBURFURUBFBRFBLUURBRFLFLULRLURBBDDLFFUURDRFDFUBDDDRDRBFRFLLUDDBDUFBLRRBDDBLFDFLRBLRBRLLRFDLDFDFLLULBLUDUDUUBULLBDBUDDBLDBRRD)
5x5x5 max solution 149 steps (DFFURRULDLDLURLBDDRRBFRURFBFBFRBDLBBFRBLRFBRBBFLULDLBLULLFRUBUFLDFFLDULDDLUURRDRFBRLULUDRBDUUUBBRFFDBDFURDBBDDRULBUDRDLLLBDRFDLRDLLFDBBUFBRURFFUFFUUFU)

143.13user 14.92system 4:06.53elapsed 64%CPU (0avgtext+0avgdata 98072maxresident)k




+ 31
- 0
misc/NOTES-6x6x6.txt View File

@@ -0,0 +1,31 @@

Initial Numbers
===============
6x6x6 min solution 190 steps (DBURDLDLFBDUUFRBUULFFBUFFBUFUBFFBBLDLLRLBULBLRFUDBURBFLLUBFDLDLDRRFRRDRFLUDDFFDBFUFDUBDLBRDRRLRUDRLURDRURLFRURFBLUBBLRDUDDDUDDRRLLLLLUDRRFRBLUFDBFRFRUFLUDURUDDFUBUBDUUFBLFDLRDUBLRBBBBRLLLFRFUDLBRFBFFLFBLBBDRDFURUFBDB)
6x6x6 max solution 296 steps (RURLLLDBBUULDUDURRFUBFULURLDLRLDFFFRUBDUFFBDRRFFLDRRUULDLLFUBDFULDLFLLBRDRLDRBRUDLRLDBRFLBUBFDBDDRDDFLDUBBDULFDRLBDLFBFRBFUUFUBRUBRULFLFBURRRURDFFRRBBFDFFLDFRBRLBLRFBBBRURLBBFUURBFUUFFFULDULBDFULDLDFBLDDBLRDBUUBBRDUD)
6x6x6 avg solution 245.0 steps
6x6x6 avg centers solution 96.0 steps
6x6x6 avg edges solution 105.0 steps

We currently do not avoid OLL or PLL (it takes too long) so it
takes us 45 moves to solve 3x3x3 at the end



Prevent OLL and avoid PLL (most of the time)
============================================
6x6x6 min solution 190 steps (DBURDLDLFBDUUFRBUULFFBUFFBUFUBFFBBLDLLRLBULBLRFUDBURBFLLUBFDLDLDRRFRRDRFLUDDFFDBFUFDUBDLBRDRRLRUDRLURDRURLFRURFBLUBBLRDUDDDUDDRRLLLLLUDRRFRBLUFDBFRFRUFLUDURUDDFUBUBDUUFBLFDLRDUBLRBBBBRLLLFRFUDLBRFBFFLFBLBBDRDFURUFBDB)
6x6x6 max solution 273 steps (RFUUFDBDDLBBLBUBBRLRURFBRDLLDDBLRBDDBRRUDFLFURFDFRRULFUUDDULUBRLUFRBDDBFRUDRLLRRFDBBRLFFDRBDFFBFFBRUFRDDBLDDFLDFRBULFFRRLBDRBRLBBLLFLLUBUULBBBFUFLUDUURRRULFUDRLRFFFUBBDRUDUDUUFBDLRLULRLUBFLDLBDFLBFFBDLDULDRFRUFLDUUUB)
6x6x6 avg solution 232.0 steps
6x6x6 avg centers solution 108.0 steps
6x6x6 avg edges solution 103.0 steps


5x5x5 edge pairing improvements
===============================
6x6x6 min solution 189 steps (LDBRDBFURDLRFLLLRFFBDFRFFDBLULDURBRFRURRDUBDFFBUUDRRUDDRLRFDFFUBBBDFUUDDLRBLFDRUDLFDFRUBFFLLLBUBLDDDRLFDURRLUBBDBBURBFRLRLDFRRLLDUBFDLUFFRBLDRLBUUDLRFDBURDBLDFBDLUFUBLBBLULUULLUDFRRFUDFFRBURRLLFRFBUFDDUBBUFBULURBBLBU)
6x6x6 max solution 237 steps (LBFDLRURFLUUUDRRFDLLLBURLRBBUBFRDURFLRURBBBBBRDFRDRDDRULLUFLLBFFUFFDLRFFDDFLFURLUULDBRBUFFDBFDBBFFLDRFBFLUDRDUDFLURLURFRDURBUFLDLLBBBBFUFDDDULBDBRRFBLURRBDUUFDFDDBRBFDFBUUBLULUDBFRUURURULBRLDLFLDURLBLFURRDDDLFLRDBBLB)
6x6x6 avg solution 214.0 steps
6x6x6 avg centers solution 106.0 steps
6x6x6 avg edges solution 86.0 steps


+ 10
- 0
misc/NOTES-7x7x7.txt View File

@@ -0,0 +1,10 @@

init numbers
============
DUULUFDLULFLLURLUDLBDDBFFLRDRRLDDLDDBDBFFFFBBURLLRBRFLDBUDFBDRFRBFRUUUBFRFRRDFLBDURRBLFFU
7x7x7 min solution 290 steps (DBDBDDFBDDLUBDLFRFRBRLLDUFFDUFRBRDFDRUFDFDRDBDBULDBDBDBUFBUFFFULLFLDURRBBRRBRLFUUUDUURBRDUUURFFFLRFLRLDLBUFRLDLDFLLFBDFUFRFFUUUFURDRFULBRFURRBUDDRBDLLRLDLLDLUURFRFBUBURBRUDBDDLRBULBULUBDBBUDRBLFFBLRBURRUFULBRLFDUFDDBULBRLBUFULUDDLLDFRDRDBBFBUBBFLFFRRUFFRLRRDRULLLFRLFULBLLBBBLDFDBRBFDULLULRFDBR)
7x7x7 max solution 322 steps (DBRFBBRLRBULFDLBBURDLBRRUUFLUFDFUFRRBUBUFRRLUFLDULBFUDLUDBDFDDFDFLDUFFFUFRRLDBBFUDUFDLRLUBUDRRRDBFUFFUBFBURLDDFLURDUFFRDRDFDLDDBURULULDDBDDRFFFBLFBDULRURRDUDUURUBLLLDFUDDDDRBUBULLRBRRLDUBLLLBLRBLDBUBLFFBDURFRURBBBBRRRUFFLLLLULFBBBLLFLBLRBFBDRRBLFUDLFULDLRRFURDRBFFUUBRBBLDBDLRBLULFBFDRDFRURFFDU)
7x7x7 avg solution 304.0 steps
7x7x7 avg centers solution 156.0 steps
7x7x7 avg edges solution 127.0 steps


+ 85
- 0
misc/TODO.txt View File

@@ -0,0 +1,85 @@

lrzip comparison

'lrzip lookup-table-4x4x4-step10-solve-UD-centers.txt'
dwalton@laptop ~/l/r/NxNxN> ls -lh lookup-table-4x4x4-step10-solve-UD-centers.txt*
-rw-rw-r-- 1 dwalton dwalton 1.2G Mar 27 07:51 lookup-table-4x4x4-step10-solve-UD-centers.txt
-rw-rw-r-- 1 dwalton dwalton 165M Mar 27 15:49 lookup-table-4x4x4-step10-solve-UD-centers.txt.lrz
dwalton@laptop ~/l/r/NxNxN>


'lrzip -z lookup-table-4x4x4-step10-solve-UD-centers.txt'
dwalton@laptop ~/l/r/NxNxN> ls -lh lookup-table-4x4x4-step10-solve-UD-centers.txt*
-rw-rw-r-- 1 dwalton dwalton 1.2G Mar 27 07:51 lookup-table-4x4x4-step10-solve-UD-centers.txt
-rw-rw-r-- 1 dwalton dwalton 132M Mar 27 16:01 lookup-table-4x4x4-step10-solve-UD-centers.txt.lrz
dwalton@laptop ~/l/r/NxNxN>
dwalton@laptop ~/l/r/NxNxN>




- code cleanup

4x4x4 last two edges
====================
- Try with and without the tweak that pairs two edges at once. This should be
faster most of the time but there are cases where if we do this it always
leads to PLL parity. Basically resolve the edges with this enabled and if it
cannot find a PLL free solution then try without.

- re-read the "pair 6 edges at once" page



Misc
====
- redo how 5x5x5 centers are solved, it is a mess, use the following instead
http://rubik.rthost.org/5x5x5_centres.htm

- redo how 555 edge parity IDs are assigned, this is also a mess at the moment


5x5x5 UD center options
=======================
Do all three of these and see which approach solves UD centers with the fewest moves.
Obviously #1 will be more moves than #2 but #2 requires a pretty huge lookup table so
do this comparison to see if #2 is worth it.

#1 - Solve U centers, then D center edges and corners while preserving U
#2 - Solve U centers (lookup table), then D center edges and corners while preserving U
#3 - Solve UD center corners (lookup table), then U center edges while preserving D, then D center edges while preserving U
#4 - Solve UD center corners (lookup table), then U center edges without preserving D, then D center edges and corners while preserving U


5x5x5 last two edges
====================
- find the patterns that require multiple parity ID sequences...create new parity IDs
from these and once we have them all, drop the "while True" loop in resolve_555_edge_parity()
and barf if we ever find a new one


solver.py
=========
- clean up the use of pos vs square_index
- clean up the use of wing vs edge

- get_solution_score()
- Instead of counting the number of steps in a solution come up with a score for
how long we think the robot would take to solve it

- compress_solution()
- combine "U U" into U2
- remove x,y,z steps

- group_edges() and get_edge_we_can_solve_with_least_moves()
DONE - lot of cut-n-paste code
- Instead of calling move_wing_to_F_west just rotate xyz to get it there. This
should save us 5-10 moves in pairing edges for 4x4x4

- bring in the python kociemba solver?


2x2x2 solver
============
- ungolf the 2x2x2 solver
- wrap your head around how the hell this thing works

+ 2507
- 0
rubikscubennnsolver/LookupTable.py
File diff suppressed because it is too large
View File


+ 178
- 0
rubikscubennnsolver/RubiksCube222.py View File

@@ -0,0 +1,178 @@

from rubikscubennnsolver import RubiksCube, SolveError
from rubikscubennnsolver.LookupTable import LookupTable
import logging

log = logging.getLogger(__name__)


moves_2x2x2 = ("U", "U'", "U2",
"L", "L'", "L2",
"F" , "F'", "F2",
"R" , "R'", "R2",
"B" , "B'", "B2",
"D" , "D'", "D2")
solved_2x2x2 = 'UUUURRRRFFFFDDDDLLLLBBBB'


class RubiksCube222(RubiksCube):

def __init__(self, state, order, colormap=None, debug=False):
RubiksCube.__init__(self, state, order, colormap, debug)

if debug:
log.setLevel(logging.DEBUG)

def phase(self):
return 'Solve 2x2x2'

def solve_non_table(self):
"""
100% of the credit for this 2x2x2 solver goes to
http://codegolf.stackexchange.com/questions/35002/solve-the-rubiks-pocket-cube

In the codegolf challenge they defined the input as

- - A B - - - -
- - C D - - - -

E F G H I J K L
M N O P Q R S T

- - U V - - - -
- - W X - - - -

But normally we number cubes like this

01 02
03 04
05 06 09 10 13 14 17 18
07 08 11 12 15 16 19 20
21 22
23 24

So we will define the former layout as "scramble" and the latter as "normal".
Convert the normal layout (sys.argv[1] must be in the 'normal' layout) to
the scramble layout.
"""

# 'normal' must be in U, R, F, D, L, B order
# This is the order used by the kociemba 3x3x3 solver so
# the rubiks-color-resolver uses this order
normal = self.get_kociemba_string(False)
log.info("NORMAL: %s" % normal)
upper = normal[0:4]
right = normal[4:8]
front = normal[8:12]
down = normal[12:16]
left = normal[16:20]
back = normal[20:24]

'''
from pprint import pformat
print "upper: %s" % pformat(upper)
print "right: %s" % pformat(right)
print "front: %s" % pformat(front)
print "down: %s" % pformat(down)
print "left: %s" % pformat(left)
print "back: %s" % pformat(back)
'''

scramble = []
scramble.extend(upper)
scramble.append(left[0])
scramble.append(left[1])
scramble.append(front[0])
scramble.append(front[1])
scramble.append(right[0])
scramble.append(right[1])
scramble.append(back[0])
scramble.append(back[1])

scramble.append(left[2])
scramble.append(left[3])
scramble.append(front[2])
scramble.append(front[3])
scramble.append(right[2])
scramble.append(right[3])
scramble.append(back[2])
scramble.append(back[3])
scramble.extend(down)

o = ''.join
data = [{''.join((' ', x)[x in scramble[12] + scramble[19] + scramble[22]]for x in scramble):[]},
{' ' * 4 + (scramble[12] * 2 + ' ' * 4 + scramble[19] * 2) * 2 + scramble[22] * 4:[]}]

from pprint import pprint
#pprint(data)

wtf_table = [
[0, 7, 2, 15, 4, 5, 6, 21, 16, 8, 3, 11, 12, 13, 14, 23, 17, 9, 1, 19, 20, 18, 22, 10],
[0, 7, 2, 15, 4, 5, 6, 21, 16, 8, 3, 11, 12, 13, 14, 23, 17, 9, 1, 19, 20, 18, 22, 10],
[0, 7, 2, 15, 4, 5, 6, 21, 16, 8, 3, 11, 12, 13, 14, 23, 17, 9, 1, 19, 20, 18, 22, 10],
[0, 7, 2, 15, 4, 5, 6, 21, 16, 8, 3, 11, 12, 13, 14, 23, 17, 9, 1, 19, 20, 18, 22, 10],
[2, 0, 3, 1, 6, 7, 8, 9, 10, 11, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
[2, 0, 3, 1, 6, 7, 8, 9, 10, 11, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
[2, 0, 3, 1, 6, 7, 8, 9, 10, 11, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
[2, 0, 3, 1, 6, 7, 8, 9, 10, 11, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
[0, 1, 13, 5, 4, 20, 14, 6, 2, 9, 10, 11, 12, 21, 15, 7, 3, 17, 18, 19, 16, 8, 22, 23],
[0, 1, 13, 5, 4, 20, 14, 6, 2, 9, 10, 11, 12, 21, 15, 7, 3, 17, 18, 19, 16, 8, 22, 23],
[0, 1, 13, 5, 4, 20, 14, 6, 2, 9, 10, 11, 12, 21, 15, 7, 3, 17, 18, 19, 16, 8, 22, 23],
[0, 1, 13, 5, 4, 20, 14, 6, 2, 9, 10, 11, 12, 21, 15, 7, 3, 17, 18, 19, 16, 8, 22, 23]
]

for h in (0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1):
for s, x in data[h].items():
for y in xrange(12):

data[h][s] = x + [y - [1, -1, 1, 3][h * y % 4]]

if s in data[1 - h]:
# pprint(data[0][s])
# pprint(data[1][s])
try:
result = ''.join('RUF'[x / 4] + " 2'"[x % 4] for x in data[0][s] + data[1][s][::-1])
except IndexError:
print("Cube is already solved")
sys.exit(0)

result = result.replace('2', '2 ')
result = result.replace("'", "' ")
for step in result.strip().split():
self.rotate(step)
return

s = ''.join(s[x] for x in wtf_table[y])

raise SolveError("Could not find a solution")

def solve_via_table(self):
'''
For grins I built a full lookup table for 2x2x2, it is too large to put in the
repo though and the solver from stackoverflow works just fine but I'll leave
this here for a rainy day.

lookup-table-2x2x2-solve.txt
============================
1 steps has 18 entries (0 percent, 0.00x previous step)
2 steps has 244 entries (0 percent, 13.56x previous step)
3 steps has 2,874 entries (0 percent, 11.78x previous step)
4 steps has 28,000 entries (0 percent, 9.74x previous step)
5 steps has 205,416 entries (0 percent, 7.34x previous step)
6 steps has 1,168,516 entries (1 percent, 5.69x previous step)
7 steps has 5,402,628 entries (6 percent, 4.62x previous step)
8 steps has 20,776,176 entries (23 percent, 3.85x previous step)
9 steps has 45,391,616 entries (51 percent, 2.18x previous step)
10 steps has 15,139,616 entries (17 percent, 0.33x previous step)
11 steps has 64,736 entries (0 percent, 0.00x previous step)

Total: 88,179,840 entries
'''
self.lt = LookupTable(self, 'lookup-table-2x2x2-solve.txt', 'all', 'UUUULLLLFFFFRRRRBBBBDDDD')
self.lt.solve()
self.compress_solution()

def solve(self):
self.solve_non_table()
self.compress_solution()


+ 29
- 0
rubikscubennnsolver/RubiksCube333.py View File

@@ -0,0 +1,29 @@

from rubikscubennnsolver import RubiksCube
from rubikscubennnsolver.RubiksCube222 import moves_2x2x2
import logging

log = logging.getLogger(__name__)

moves_3x3x3 = moves_2x2x2
solved_3x3x3 = 'UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB'


class RubiksCube333(RubiksCube):

def __init__(self, state, order, colormap=None, debug=False):
RubiksCube.__init__(self, state, order, colormap, debug)

if debug:
log.setLevel(logging.DEBUG)

def phase(self):
return 'Solve 3x3x3'

def solve(self):
self.rotate_U_to_U()
self.rotate_F_to_F()

if self.get_state_all() != 'UUUUUUUUULLLLLLLLLFFFFFFFFFRRRRRRRRRBBBBBBBBBDDDDDDDDD':
self.solve_333()
self.compress_solution()

+ 2700
- 0
rubikscubennnsolver/RubiksCube444.py
File diff suppressed because it is too large
View File


+ 1728
- 0
rubikscubennnsolver/RubiksCube555.py
File diff suppressed because it is too large
View File


+ 760
- 0
rubikscubennnsolver/RubiksCube666.py View File

@@ -0,0 +1,760 @@

from collections import OrderedDict
from pprint import pformat
from rubikscubennnsolver import RubiksCube, ImplementThis
from rubikscubennnsolver.RubiksCube444 import RubiksCube444, solved_4x4x4
from rubikscubennnsolver.RubiksCube555 import RubiksCube555, solved_5x5x5
from rubikscubennnsolver.RubiksSide import Side, SolveError
from rubikscubennnsolver.LookupTable import LookupTable, LookupTableIDA, NoIDASolution
import logging
import math
import os
import random
import re
import subprocess
import sys

log = logging.getLogger(__name__)


moves_6x6x6 = ("U", "U'", "U2", "Uw", "Uw'", "Uw2", "3Uw", "3Uw'", "3Uw2",
"L", "L'", "L2", "Lw", "Lw'", "Lw2", "3Lw", "3Lw'", "3Lw2",
"F" , "F'", "F2", "Fw", "Fw'", "Fw2", "3Fw", "3Fw'", "3Fw2",
"R" , "R'", "R2", "Rw", "Rw'", "Rw2", "3Rw", "3Rw'", "3Rw2",
"B" , "B'", "B2", "Bw", "Bw'", "Bw2", "3Bw", "3Bw'", "3Bw2",
"D" , "D'", "D2", "Dw", "Dw'", "Dw2", "3Dw", "3Dw'", "3Dw2")
solved_6x6x6 = 'UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'


class RubiksCube666(RubiksCube):
"""
6x6x6 strategy
- stage UD centers to sides U or D (use IDA)
- stage LR centers to sides L or R...this in turn stages FB centers to sides F or B
- solve all centers (use IDA)
- pair edges
- solve as 3x3x3
"""

def __init__(self, state, order, colormap=None, debug=False):
RubiksCube.__init__(self, state, order, colormap)

if debug:
log.setLevel(logging.DEBUG)

def lt_init(self):
if self.lt_init_called:
return
self.lt_init_called = True

'''
Stage the inner X-centers
24!/(8!*16!) is 735,471

lookup-table-6x6x6-step10-UD-inner-x-centers-stage.txt
======================================================
1 steps has 5 entries (0 percent, 0.00x previous step)
2 steps has 82 entries (0 percent, 16.40x previous step)
3 steps has 1,206 entries (0 percent, 14.71x previous step)
4 steps has 14,116 entries (1 percent, 11.70x previous step)
5 steps has 123,404 entries (16 percent, 8.74x previous step)
6 steps has 422,508 entries (57 percent, 3.42x previous step)
7 steps has 173,254 entries (23 percent, 0.41x previous step)
8 steps has 896 entries (0 percent, 0.01x previous step)

Total: 735,471 entries
'''
self.lt_UD_inner_x_centers_stage = LookupTable(self,
'lookup-table-6x6x6-step10-UD-inner-x-centers-stage.txt',
'666-UD-inner-X-centers-stage',
'066000000000000000000660',
True, # state_hex
modulo=735473)

'''
lookup-table-6x6x6-step21-UD-oblique-edge-pairing-left-only.txt
lookup-table-6x6x6-step22-UD-oblique-edge-pairing-right-only.txt
================================================================
1 steps has 5 entries (0 percent, 0.00x previous step)
2 steps has 82 entries (0 percent, 16.40x previous step)
3 steps has 1,198 entries (0 percent, 14.61x previous step)
4 steps has 13,818 entries (1 percent, 11.53x previous step)
5 steps has 115,638 entries (15 percent, 8.37x previous step)
6 steps has 399,478 entries (54 percent, 3.45x previous step)
7 steps has 204,612 entries (27 percent, 0.51x previous step)
8 steps has 640 entries (0 percent, 0.00x previous step)

Total: 735,471 entries
'''
self.lt_UD_oblique_edge_pairing_left_only = LookupTable(self,
'lookup-table-6x6x6-step21-UD-oblique-edge-pairing-left-only.txt',
'666-UD-oblique-edge-pairing-left-only',
'990000000099',
True, # state_hex
modulo=735473)

self.lt_UD_oblique_edge_pairing_right_only = LookupTable(self,
'lookup-table-6x6x6-step22-UD-oblique-edge-pairing-right-only.txt',
'666-UD-oblique-edge-pairing-right-only',
'660000000066',
True, # state_hex
modulo=735473)

'''
Now pair the UD oblique edges so that we can reduce the 6x6x6 centers to a 5x5x5
(24!/(8!*16!))^2 is 540,917,591,841 so this is too large for us to build so use
IDA and build it 8 steps deep.

Our prune tables will be to solve on the left or right oblique edges. Each of these
tables are 24!/(8!*16!) or 735,471
735471/540917591841 is 0.0000013596729171

lookup-table-6x6x6-step20-UD-oblique-edge-pairing.txt
=====================================================
1 steps has 5 entries (0 percent, 0.00x previous step)
2 steps has 82 entries (0 percent, 16.40x previous step)
3 steps has 1,434 entries (0 percent, 17.49x previous step)
4 steps has 24,198 entries (0 percent, 16.87x previous step)
5 steps has 405,916 entries (0 percent, 16.77x previous step)
6 steps has 6,839,392 entries (5 percent, 16.85x previous step)

Total: 7,271,027 entries
'''
self.lt_UD_oblique_edge_pairing = LookupTableIDA(self,
'lookup-table-6x6x6-step20-UD-oblique-edge-pairing.txt',
'666-UD-oblique-edge-pairing',
'ff00000000ff',
True, # state_hex
moves_6x6x6,

# These would break up the staged UD inner x-centers
("3Rw", "3Rw'", "3Lw", "3Lw'", "3Fw", "3Fw'", "3Bw", "3Bw'"),

# prune tables
(self.lt_UD_oblique_edge_pairing_left_only,
self.lt_UD_oblique_edge_pairing_right_only),
modulo=7271027)
'''
16!/(8!*8!) is 12,870

lookup-table-6x6x6-step30-LR-inner-x-centers-stage.txt
======================================================
1 steps has 3 entries (0 percent)
2 steps has 29 entries (0 percent)
3 steps has 234 entries (1 percent)
4 steps has 1,246 entries (9 percent)
5 steps has 4,466 entries (34 percent)
6 steps has 6,236 entries (48 percent)
7 steps has 656 entries (5 percent)

Total: 12,870 entries
'''
self.lt_LR_inner_x_centers_stage = LookupTable(self,
'lookup-table-6x6x6-step30-LR-inner-x-centers-stage.txt',
'666-LR-inner-X-centers-stage',
'000006600000066000000000',
True, # state_hex
modulo=12889)

'''
lookup-table-6x6x6-step41-LR-oblique-pairing-left-only.txt
lookup-table-6x6x6-step42-LR-oblique-pairing-right-only.txt
==========================================================
1 steps has 3 entries (0 percent, 0.00x previous step)
2 steps has 29 entries (0 percent, 9.67x previous step)
3 steps has 238 entries (1 percent, 8.21x previous step)
4 steps has 742 entries (5 percent, 3.12x previous step)
5 steps has 1836 entries (14 percent, 2.47x previous step)
6 steps has 4405 entries (34 percent, 2.40x previous step)
7 steps has 3774 entries (29 percent, 0.86x previous step)
8 steps has 1721 entries (13 percent, 0.46x previous step)
9 steps has 122 entries (0 percent, 0.07x previous step)

Total: 12870 entries
'''
self.lt_LR_oblique_edge_pairing_left_only = LookupTable(self,
'lookup-table-6x6x6-step41-LR-oblique-pairing-left-only.txt',
'666-LR-oblique-edge-pairing-left-only',
'99009900',
True, # state_hex
modulo=12889)

self.lt_LR_oblique_edge_pairing_right_only = LookupTable(self,
'lookup-table-6x6x6-step42-LR-oblique-pairing-right-only.txt',
'666-LR-oblique-edge-pairing-right-only',
'66006600',
True, # state_hex
modulo=12889)
'''
(16!/(8!*8!))^2 is 165,636,900
I only built this 9 deep to keep it small thus the IDA

lookup-table-6x6x6-step40-LR-oblique-pairing.txt
================================================
1 steps has 3 entries (0 percent)
2 steps has 29 entries (0 percent)
3 steps has 286 entries (0 percent)
4 steps has 2,052 entries (0 percent)
5 steps has 16,348 entries (0 percent)
6 steps has 127,859 entries (0 percent)
7 steps has 844,248 entries (0 percent)
8 steps has 4,623,585 entries (2 percent)
9 steps has 19,019,322 entries (11 percent)
10 steps has 47,544,426 entries (28 percent)
11 steps has 61,805,656 entries (37 percent)
12 steps has 28,890,234 entries (17 percent)
13 steps has 2,722,462 entries (1 percent)
14 steps has 40,242 entries (0 percent)
15 steps has 148 entries (0 percent)

Total: 165,636,900 entries
'''
self.lt_LR_oblique_edge_pairing = LookupTableIDA(self,
'lookup-table-6x6x6-step40-LR-oblique-pairing.txt',
'666-LR-oblique-edge-pairing',
'ff00ff00',
True, # state_hex
moves_6x6x6,

# These would break up the staged UD inner x-centers
("3Rw", "3Rw'", "3Lw", "3Lw'", "3Fw", "3Fw'", "3Bw", "3Bw'", # do not mess up UD x-centers
"Rw", "Rw'", "Lw", "Lw'", "Fw", "Fw'", "Bw", "Bw'", # do not mess up UD oblique pairs
"3Uw", "3Uw'", "3Dw", "3Dw'"), # do not mess up LR x-centers

# prune tables
(self.lt_LR_oblique_edge_pairing_left_only,
self.lt_LR_oblique_edge_pairing_right_only),
modulo=24633733)

'''
lookup-table-6x6x6-step50-UD-solve-inner-x-center-and-oblique-edges.txt
========================================================================
1 steps has 9 entries (0 percent, 0.00x previous step)
2 steps has 47 entries (0 percent, 5.22x previous step)
3 steps has 232 entries (0 percent, 4.94x previous step)
4 steps has 1,001 entries (0 percent, 4.31x previous step)
5 steps has 4,266 entries (1 percent, 4.26x previous step)
6 steps has 16,697 entries (4 percent, 3.91x previous step)
7 steps has 52,894 entries (15 percent, 3.17x previous step)
8 steps has 114,134 entries (33 percent, 2.16x previous step)
9 steps has 113,888 entries (33 percent, 1.00x previous step)
10 steps has 37,136 entries (10 percent, 0.33x previous step)
11 steps has 2,696 entries (0 percent, 0.07x previous step)

Total: 343,000 entries
'''
self.lt_UD_solve_inner_x_centers_and_oblique_edges = LookupTable(self,
'lookup-table-6x6x6-step50-UD-solve-inner-x-center-and-oblique-edges.txt',
'666-UD-centers-oblique-edges-solve',
'xUUxUUUUUUUUxUUxxDDxDDDDDDDDxDDx',
False, # state_hex
modulo=343019)

'''
lookup-table-6x6x6-step61-LR-solve-inner-x-center-and-oblique-edges.txt
========================================================================
1 steps has 5 entries (0 percent, 0.00x previous step)
2 steps has 26 entries (0 percent, 5.20x previous step)
3 steps has 86 entries (0 percent, 3.31x previous step)
4 steps has 356 entries (0 percent, 4.14x previous step)
5 steps has 1,186 entries (0 percent, 3.33x previous step)
6 steps has 4,264 entries (1 percent, 3.60x previous step)
7 steps has 12,946 entries (3 percent, 3.04x previous step)
8 steps has 35,741 entries (10 percent, 2.76x previous step)
9 steps has 77,322 entries (22 percent, 2.16x previous step)
10 steps has 111,116 entries (32 percent, 1.44x previous step)
11 steps has 80,988 entries (23 percent, 0.73x previous step)
12 steps has 18,436 entries (5 percent, 0.23x previous step)
13 steps has 528 entries (0 percent, 0.03x previous step)

Total: 343,000 entries
'''
self.lt_LR_solve_inner_x_centers_and_oblique_edges = LookupTable(self,
'lookup-table-6x6x6-step61-LR-solve-inner-x-center-and-oblique-edges.txt',
'666-LR-centers-oblique-edges-solve',
'xLLxLLLLLLLLxLLxxRRxRRRRRRRRxRRx',
False, # state_hex
modulo=343019)

'''
lookup-table-6x6x6-step62-FB-solve-inner-x-center-and-oblique-edges.txt
========================================================================
1 steps has 5 entries (0 percent, 0.00x previous step)
2 steps has 26 entries (0 percent, 5.20x previous step)
3 steps has 86 entries (0 percent, 3.31x previous step)
4 steps has 356 entries (0 percent, 4.14x previous step)
5 steps has 1,186 entries (0 percent, 3.33x previous step)
6 steps has 4,264 entries (1 percent, 3.60x previous step)
7 steps has 12,946 entries (3 percent, 3.04x previous step)
8 steps has 35,741 entries (10 percent, 2.76x previous step)
9 steps has 77,322 entries (22 percent, 2.16x previous step)
10 steps has 111,116 entries (32 percent, 1.44x previous step)
11 steps has 80,988 entries (23 percent, 0.73x previous step)
12 steps has 18,436 entries (5 percent, 0.23x previous step)
13 steps has 528 entries (0 percent, 0.03x previous step)

Total: 343,000 entries
'''
self.lt_FB_solve_inner_x_centers_and_oblique_edges = LookupTable(self,
'lookup-table-6x6x6-step62-FB-solve-inner-x-center-and-oblique-edges.txt',
'666-FB-centers-oblique-edges-solve',
'xFFxFFFFFFFFxFFxxBBxBBBBBBBBxBBx',
False, # state_hex
modulo=343019)

'''
lookup-table-6x6x6-step60-LFRB-solve-inner-x-center-and-oblique-edges.txt
==========================================================================
1 steps has 5 entries (0 percent, 0.00x previous step)
2 steps has 54 entries (0 percent, 10.80x previous step)
3 steps has 420 entries (0 percent, 7.78x previous step)
4 steps has 2,703 entries (0 percent, 6.44x previous step)
5 steps has 18,740 entries (0 percent, 6.93x previous step)
6 steps has 118,707 entries (0 percent, 6.33x previous step)
7 steps has 707,156 entries (2 percent, 5.96x previous step)
8 steps has 3,945,650 entries (15 percent, 5.58x previous step)
9 steps has 20,886,476 entries (81 percent, 5.29x previous step)

Total: 25,679,911 entries
'''
self.lt_LFRB_solve_inner_x_centers_and_oblique_edges = LookupTableIDA(self,
'lookup-table-6x6x6-step60-LFRB-solve-inner-x-center-and-oblique-edges.txt',
'666-LFRB-centers-oblique-edges-solve',
'xLLxLLLLLLLLxLLxxFFxFFFFFFFFxFFxxRRxRRRRRRRRxRRxxBBxBBBBBBBBxBBx',
False, # state_hex
moves_6x6x6,

("3Rw", "3Rw'", "3Lw", "3Lw'", "3Fw", "3Fw'", "3Bw", "3Bw'", "3Uw", "3Uw'", "3Dw", "3Dw'", # do not mess up staged centers
"Rw", "Rw'", "Lw", "Lw'", "Fw", "Fw'", "Bw", "Bw'", "Uw", "Uw'", "Dw", "Dw'", # do not mess up staged centers
"3Rw2", "3Lw2", "3Fw2", "3Bw2", "Rw2", "Lw2", "Fw2", "Bw2", # do not mess up solved UD
"L", "L'", "L2", "R", "R'", "R2"), # do not mess up LR sides that we staged via self.lt_LR_solve_inner_x_centers_and_oblique_edges.solve()

# prune tables
(self.lt_LR_solve_inner_x_centers_and_oblique_edges,
self.lt_FB_solve_inner_x_centers_and_oblique_edges),
modulo=4793471)

def populate_fake_555_for_ULFRBD(self, fake_555):

for x in xrange(1, 151):
fake_555.state[x] = 'x'

# Upper
fake_555.state[7] = self.state[8]
fake_555.state[8] = self.state[9]
fake_555.state[9] = self.state[11]
fake_555.state[12] = self.state[14]
fake_555.state[13] = self.state[15]
fake_555.state[14] = self.state[17]
fake_555.state[17] = self.state[26]
fake_555.state[18] = self.state[27]
fake_555.state[19] = self.state[29]

# Left
fake_555.state[32] = self.state[44]
fake_555.state[33] = self.state[45]
fake_555.state[34] = self.state[47]
fake_555.state[37] = self.state[50]
fake_555.state[38] = self.state[51]
fake_555.state[39] = self.state[53]
fake_555.state[42] = self.state[62]
fake_555.state[43] = self.state[63]
fake_555.state[44] = self.state[65]

# Front
fake_555.state[57] = self.state[80]
fake_555.state[58] = self.state[81]
fake_555.state[59] = self.state[83]
fake_555.state[62] = self.state[86]
fake_555.state[63] = self.state[87]
fake_555.state[64] = self.state[89]
fake_555.state[67] = self.state[98]
fake_555.state[68] = self.state[99]
fake_555.state[69] = self.state[101]

# Right
fake_555.state[82] = self.state[116]
fake_555.state[83] = self.state[117]
fake_555.state[84] = self.state[119]
fake_555.state[87] = self.state[122]
fake_555.state[88] = self.state[123]
fake_555.state[89] = self.state[125]
fake_555.state[92] = self.state[134]
fake_555.state[93] = self.state[135]
fake_555.state[94] = self.state[137]

# Back
fake_555.state[107] = self.state[152]
fake_555.state[108] = self.state[153]
fake_555.state[109] = self.state[155]
fake_555.state[112] = self.state[158]
fake_555.state[113] = self.state[159]
fake_555.state[114] = self.state[161]
fake_555.state[117] = self.state[170]
fake_555.state[118] = self.state[171]
fake_555.state[119] = self.state[173]

# Down
fake_555.state[132] = self.state[188]
fake_555.state[133] = self.state[189]
fake_555.state[134] = self.state[191]
fake_555.state[137] = self.state[194]
fake_555.state[138] = self.state[195]
fake_555.state[139] = self.state[197]
fake_555.state[142] = self.state[206]
fake_555.state[143] = self.state[207]
fake_555.state[144] = self.state[209]

def group_centers_stage_UD(self):
self.lt_UD_inner_x_centers_stage.solve()

# This one can take a while so we do some tricks to speed it up
# - first try to find a solution without solving either prune table beforehand
# - if that doesn't work, solve the left_only prune table and try again
# - if that doesn't work, solve the right_only prune table and let it run
#
# We do this because for some cubes if you solve the left_only prune table it
# really speeds up IDA while for other cubes it doesn't but solving the right_only
# prune table will speed things up.
try:
self.lt_UD_oblique_edge_pairing.solve(8)
except NoIDASolution:
original_state = self.state[:]
original_solution = self.solution[:]
self.lt_UD_oblique_edge_pairing_left_only.solve() # speed up IDA

try:
self.lt_UD_oblique_edge_pairing.solve(9)
except NoIDASolution:
self.state = original_state
self.solution = original_solution
self.lt_UD_oblique_edge_pairing_right_only.solve() # speed up IDA
self.lt_UD_oblique_edge_pairing.solve(99)

#self.print_cube()
#sys.exit(0)

def group_centers_guts(self):
self.lt_init()
self.group_centers_stage_UD()

self.lt_LR_inner_x_centers_stage.solve()
self.lt_LR_oblique_edge_pairing.solve(99)
log.info("inner x-center and oblique edges staged, %d steps in" % self.get_solution_len_minus_rotates(self.solution))
self.print_cube()
log.info("")
log.info("")
log.info("")
log.info("")
log.info("")

# Reduce the centers to 5x5x5 centers
# - solve the UD inner x-centers and pair the UD oblique edges
# - solve the LR inner x-centers and pair the LR oblique edges
# - solve the FB inner x-centers and pair the FB oblique edges
self.lt_UD_solve_inner_x_centers_and_oblique_edges.solve()

self.lt_LR_solve_inner_x_centers_and_oblique_edges.solve() # speed up IDA
self.lt_LFRB_solve_inner_x_centers_and_oblique_edges.solve(99)
log.info("inner x-center and oblique edges paired, %d steps in" % self.get_solution_len_minus_rotates(self.solution))
self.print_cube()
log.info("")
log.info("")
log.info("")
log.info("")
log.info("")

# At this point the 6x6x6 centers have been reduced to 5x5x5 centers
fake_555 = RubiksCube555(solved_5x5x5)
fake_555.lt_init()
self.populate_fake_555_for_ULFRBD(fake_555)
fake_555.group_centers_guts()

for step in fake_555.solution:
self.rotate(step)

log.info("Took %d steps to solve centers" % self.get_solution_len_minus_rotates(self.solution))

def pair_inside_edges_via_444(self):
fake_444 = RubiksCube444(solved_4x4x4)
fake_444.lt_init()

# The corners don't matter but it does make troubleshooting easier if they match
fake_444.state[1] = self.state[1]
fake_444.state[4] = self.state[6]
fake_444.state[13] = self.state[31]
fake_444.state[16] = self.state[36]
fake_444.state[17] = self.state[37]
fake_444.state[20] = self.state[42]
fake_444.state[29] = self.state[67]
fake_444.state[32] = self.state[72]
fake_444.state[33] = self.state[73]
fake_444.state[36] = self.state[78]
fake_444.state[45] = self.state[103]
fake_444.state[48] = self.state[108]
fake_444.state[49] = self.state[109]
fake_444.state[52] = self.state[114]
fake_444.state[61] = self.state[139]
fake_444.state[64] = self.state[144]
fake_444.state[65] = self.state[145]
fake_444.state[68] = self.state[150]
fake_444.state[77] = self.state[175]
fake_444.state[80] = self.state[180]
fake_444.state[81] = self.state[181]
fake_444.state[84] = self.state[186]
fake_444.state[93] = self.state[211]
fake_444.state[96] = self.state[216]

# Upper
fake_444.state[2] = self.state[3]
fake_444.state[3] = self.state[4]
fake_444.state[5] = self.state[13]
fake_444.state[8] = self.state[18]
fake_444.state[9] = self.state[19]
fake_444.state[12] = self.state[24]
fake_444.state[14] = self.state[33]
fake_444.state[15] = self.state[34]

# Left
fake_444.state[18] = self.state[39]
fake_444.state[19] = self.state[40]
fake_444.state[21] = self.state[49]
fake_444.state[24] = self.state[54]
fake_444.state[25] = self.state[55]
fake_444.state[28] = self.state[60]
fake_444.state[30] = self.state[69]
fake_444.state[31] = self.state[70]

# Front
fake_444.state[34] = self.state[75]
fake_444.state[35] = self.state[76]
fake_444.state[37] = self.state[85]
fake_444.state[40] = self.state[90]
fake_444.state[41] = self.state[91]
fake_444.state[44] = self.state[96]
fake_444.state[46] = self.state[105]
fake_444.state[47] = self.state[106]

# Right
fake_444.state[50] = self.state[111]
fake_444.state[51] = self.state[112]
fake_444.state[53] = self.state[121]
fake_444.state[56] = self.state[126]
fake_444.state[57] = self.state[127]
fake_444.state[60] = self.state[132]
fake_444.state[62] = self.state[141]
fake_444.state[63] = self.state[142]

# Back
fake_444.state[66] = self.state[147]
fake_444.state[67] = self.state[148]
fake_444.state[69] = self.state[157]
fake_444.state[72] = self.state[162]
fake_444.state[73] = self.state[163]
fake_444.state[76] = self.state[168]
fake_444.state[78] = self.state[177]
fake_444.state[79] = self.state[178]

# Down
fake_444.state[82] = self.state[183]
fake_444.state[83] = self.state[184]
fake_444.state[85] = self.state[193]
fake_444.state[88] = self.state[198]
fake_444.state[89] = self.state[199]
fake_444.state[92] = self.state[204]
fake_444.state[94] = self.state[213]
fake_444.state[95] = self.state[214]

fake_444.group_edges()

for step in fake_444.solution:
if step == 'EDGES_GROUPED':
continue

if step.startswith('4'):
step = '6' + step[1:]
elif step.startswith('3'):
raise ImplementThis('4x4x4 steps starts with 3')
elif step in ("Uw", "Uw'", "Uw2",
"Lw", "Lw'", "Lw2",
"Fw", "Fw'", "Fw2",
"Rw", "Rw'", "Rw2",
"Bw", "Bw'", "Bw2",
"Dw", "Dw'", "Dw2"):
step = '3' + step

# log.warning("fake_444 step %s" % step)
self.rotate(step)

log.info("Inside edges are paired, %d steps in" % self.get_solution_len_minus_rotates(self.solution))

def pair_outside_edges_via_555(self):
fake_555 = RubiksCube555(solved_5x5x5)
fake_555.lt_init()

# The corners matter for avoiding PLL
fake_555.state[1] = self.state[1]
fake_555.state[5] = self.state[6]
fake_555.state[21] = self.state[31]
fake_555.state[25] = self.state[36]
fake_555.state[26] = self.state[37]
fake_555.state[30] = self.state[42]
fake_555.state[46] = self.state[67]
fake_555.state[50] = self.state[72]
fake_555.state[51] = self.state[73]
fake_555.state[55] = self.state[78]
fake_555.state[71] = self.state[103]
fake_555.state[75] = self.state[108]
fake_555.state[76] = self.state[109]
fake_555.state[80] = self.state[114]
fake_555.state[96] = self.state[139]
fake_555.state[100] = self.state[144]
fake_555.state[101] = self.state[145]
fake_555.state[105] = self.state[150]
fake_555.state[121] = self.state[175]
fake_555.state[125] = self.state[180]
fake_555.state[126] = self.state[181]
fake_555.state[130] = self.state[186]
fake_555.state[146] = self.state[211]
fake_555.state[150] = self.state[216]

# Upper
fake_555.state[2] = self.state[2]
fake_555.state[3] = self.state[3]
fake_555.state[4] = self.state[5]
fake_555.state[6] = self.state[7]
fake_555.state[10] = self.state[12]
fake_555.state[11] = self.state[13]
fake_555.state[15] = self.state[18]
fake_555.state[16] = self.state[25]
fake_555.state[20] = self.state[30]
fake_555.state[22] = self.state[32]
fake_555.state[23] = self.state[33]
fake_555.state[24] = self.state[35]

# Left
fake_555.state[27] = self.state[38]
fake_555.state[28] = self.state[39]
fake_555.state[29] = self.state[41]
fake_555.state[31] = self.state[43]
fake_555.state[35] = self.state[48]
fake_555.state[36] = self.state[49]
fake_555.state[40] = self.state[54]
fake_555.state[41] = self.state[61]
fake_555.state[45] = self.state[66]
fake_555.state[47] = self.state[68]
fake_555.state[48] = self.state[69]
fake_555.state[49] = self.state[71]

# Front
fake_555.state[52] = self.state[74]
fake_555.state[53] = self.state[75]
fake_555.state[54] = self.state[77]
fake_555.state[56] = self.state[79]
fake_555.state[60] = self.state[84]
fake_555.state[61] = self.state[85]
fake_555.state[65] = self.state[90]
fake_555.state[66] = self.state[97]
fake_555.state[70] = self.state[102]
fake_555.state[72] = self.state[104]
fake_555.state[73] = self.state[105]
fake_555.state[74] = self.state[107]

# Right
fake_555.state[77] = self.state[110]
fake_555.state[78] = self.state[111]
fake_555.state[79] = self.state[113]
fake_555.state[81] = self.state[115]
fake_555.state[85] = self.state[120]
fake_555.state[86] = self.state[121]
fake_555.state[90] = self.state[126]
fake_555.state[91] = self.state[133]
fake_555.state[95] = self.state[138]
fake_555.state[97] = self.state[140]
fake_555.state[98] = self.state[141]
fake_555.state[99] = self.state[143]

# Back
fake_555.state[102] = self.state[146]
fake_555.state[103] = self.state[147]
fake_555.state[104] = self.state[149]
fake_555.state[106] = self.state[151]
fake_555.state[110] = self.state[156]
fake_555.state[111] = self.state[157]
fake_555.state[115] = self.state[162]
fake_555.state[116] = self.state[169]
fake_555.state[120] = self.state[174]
fake_555.state[122] = self.state[176]
fake_555.state[123] = self.state[177]
fake_555.state[124] = self.state[179]

# Down
fake_555.state[127] = self.state[182]
fake_555.state[128] = self.state[183]
fake_555.state[129] = self.state[185]
fake_555.state[131] = self.state[187]
fake_555.state[135] = self.state[192]
fake_555.state[136] = self.state[193]
fake_555.state[140] = self.state[198]
fake_555.state[141] = self.state[205]
fake_555.state[145] = self.state[210]
fake_555.state[147] = self.state[212]
fake_555.state[148] = self.state[213]
fake_555.state[149] = self.state[215]

#self.print_cube()
#fake_555.print_cube()
fake_555.avoid_pll = True
fake_555.group_edges()

for step in fake_555.solution:
if step == 'EDGES_GROUPED':
continue

if step.startswith('5'):
step = '6' + step[1:]
elif step.startswith('3'):
step = '4' + step[1:]

self.rotate(step)

log.info("Outside edges are paired, %d steps in" % self.get_solution_len_minus_rotates(self.solution))

def group_edges(self):
"""
Create a fake 444 to pair the inside edges
Create a fake 555 to pair the outside edges
"""

if not self.get_non_paired_edges():
self.solution.append('EDGES_GROUPED')
return

self.lt_init()
self.pair_inside_edges_via_444()
self.pair_outside_edges_via_555()
self.solution.append('EDGES_GROUPED')

def phase(self):
if self._phase is None:
self._phase = 'Stage UD centers'
return self._phase

if self._phase == 'Stage UD centers':
if self.UD_centers_staged():
self._phase = 'Stage LR centers'
return self._phase

if self._phase == 'Stage LR centers':
if self.LR_centers_staged():
self._phase = 'Solve Centers'

if self._phase == 'Solve Centers':
if self.centers_solved():
self._phase = 'Pair Edges'

if self._phase == 'Pair Edges':
if not self.get_non_paired_edges():
self._phase = 'Solve 3x3x3'

return self._phase

+ 1291
- 0
rubikscubennnsolver/RubiksCube777.py
File diff suppressed because it is too large
View File


+ 450
- 0
rubikscubennnsolver/RubiksCubeNNN.py View File

@@ -0,0 +1,450 @@

from pprint import pformat
from rubikscubennnsolver import RubiksCube, ImplementThis
from rubikscubennnsolver.RubiksCube444 import RubiksCube444, solved_4x4x4
from rubikscubennnsolver.RubiksCube555 import RubiksCube555, solved_5x5x5
from rubikscubennnsolver.RubiksCube666 import RubiksCube666, solved_6x6x6
import logging
import sys

log = logging.getLogger(__name__)


class RubiksCubeNNNOdd(RubiksCube):

def __init__(self, state, order, colormap, debug=False):
RubiksCube.__init__(self, state, order, colormap)

if debug:
log.setLevel(logging.DEBUG)


class RubiksCubeNNNEven(RubiksCube):

def __init__(self, state, order, colormap, debug=False):
RubiksCube.__init__(self, state, order, colormap)

if debug:
log.setLevel(logging.DEBUG)

def group_centers_guts(self):

# Group UD centers
# - create a fake 6x6x6 to solve the inside 4x4 block
fake_666 = RubiksCube666(solved_6x6x6)
start_666 = 0
start_NNN = 0

for x in range(6):
start_NNN_row1 = start_NNN + (((self.size/2) - 2) * self.size) + ((self.size/2) - 1)
start_NNN_row2 = start_NNN_row1 + self.size
start_NNN_row3 = start_NNN_row2 + self.size
start_NNN_row4 = start_NNN_row3 + self.size

log.info("%d: start_NNN_row1 %d, row2 %d, row3 %d row4 %d" %
(x, start_NNN_row1, start_NNN_row2, start_NNN_row3, start_NNN_row4))

fake_666.state[start_666+8] = self.state[start_NNN_row1]
fake_666.state[start_666+9] = self.state[start_NNN_row1+1]
fake_666.state[start_666+10] = self.state[start_NNN_row1+2]
fake_666.state[start_666+11] = self.state[start_NNN_row1+3]

fake_666.state[start_666+14] = self.state[start_NNN_row2]
fake_666.state[start_666+15] = self.state[start_NNN_row2+1]
fake_666.state[start_666+16] = self.state[start_NNN_row2+2]
fake_666.state[start_666+17] = self.state[start_NNN_row2+3]

fake_666.state[start_666+20] = self.state[start_NNN_row3]
fake_666.state[start_666+21] = self.state[start_NNN_row3+1]
fake_666.state[start_666+22] = self.state[start_NNN_row3+2]
fake_666.state[start_666+23] = self.state[start_NNN_row3+3]

fake_666.state[start_666+26] = self.state[start_NNN_row4]
fake_666.state[start_666+27] = self.state[start_NNN_row4+1]
fake_666.state[start_666+28] = self.state[start_NNN_row4+2]
fake_666.state[start_666+29] = self.state[start_NNN_row4+3]
start_666 += 36
start_NNN += (self.size * self.size)

# Group LR centers (in turn groups FB)
fake_666.print_cube()
fake_666.lt_init()
#fake_666.group_centers_stage_UD()
fake_666.group_centers_guts()
fake_666.print_solution()
fake_666.print_cube()

half_size = int(self.size/2)

for step in fake_666.solution:
if step.startswith("3"):
self.rotate(str(half_size) + step[1:])
elif "w" in step:
self.rotate(str(half_size - 1) + step)
else:
self.rotate(step)

# Solve UD centers
# Solve LRFB centers
self.print_cube()

# still more work to do here so go ahead and exit
sys.exit(0)

def pair_inside_edges_via_444(self):
fake_444 = RubiksCube444(solved_4x4x4)
fake_444.lt_init()

# The corners don't matter but it does make troubleshooting easier if they match
start_index = 0
fake_444.state[1] = self.state[start_index+1]
fake_444.state[4] = self.state[start_index + self.size]
fake_444.state[13] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_444.state[16] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

fake_444.state[17] = self.state[start_index+1]
fake_444.state[20] = self.state[start_index + self.size]
fake_444.state[29] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_444.state[32] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

fake_444.state[33] = self.state[start_index+1]
fake_444.state[36] = self.state[start_index + self.size]
fake_444.state[45] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_444.state[48] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

fake_444.state[49] = self.state[start_index+1]
fake_444.state[52] = self.state[start_index + self.size]
fake_444.state[61] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_444.state[64] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

fake_444.state[65] = self.state[start_index+1]
fake_444.state[68] = self.state[start_index + self.size]
fake_444.state[77] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_444.state[80] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

fake_444.state[81] = self.state[start_index+1]
fake_444.state[84] = self.state[start_index + self.size]
fake_444.state[93] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_444.state[96] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

# Upper
half_size = int(self.size/2)
start_index = 0
fake_444.state[2] = self.state[start_index + half_size]
fake_444.state[3] = self.state[start_index + half_size + 1]
fake_444.state[5] = self.state[start_index + (self.size * (half_size-1)) + 1]
fake_444.state[8] = self.state[start_index + (self.size * half_size)]
fake_444.state[9] = self.state[start_index + (self.size * half_size) + 1]
fake_444.state[12] = self.state[start_index + (self.size * (half_size+1))]
fake_444.state[14] = self.state[start_index + (self.size * self.size) - half_size]
fake_444.state[15] = self.state[start_index + (self.size * self.size) - half_size + 1]
start_index += self.size * self.size

# Left
fake_444.state[18] = self.state[start_index + half_size]
fake_444.state[19] = self.state[start_index + half_size + 1]
fake_444.state[21] = self.state[start_index + (self.size * (half_size-1)) + 1]
fake_444.state[24] = self.state[start_index + (self.size * half_size)]
fake_444.state[25] = self.state[start_index + (self.size * half_size) + 1]
fake_444.state[28] = self.state[start_index + (self.size * (half_size+1))]
fake_444.state[30] = self.state[start_index + (self.size * self.size) - half_size]
fake_444.state[31] = self.state[start_index + (self.size * self.size) - half_size + 1]
start_index += self.size * self.size

# Front
fake_444.state[34] = self.state[start_index + half_size]
fake_444.state[35] = self.state[start_index + half_size + 1]
fake_444.state[37] = self.state[start_index + (self.size * (half_size-1)) + 1]
fake_444.state[40] = self.state[start_index + (self.size * half_size)]
fake_444.state[41] = self.state[start_index + (self.size * half_size) + 1]
fake_444.state[44] = self.state[start_index + (self.size * (half_size+1))]
fake_444.state[46] = self.state[start_index + (self.size * self.size) - half_size]
fake_444.state[47] = self.state[start_index + (self.size * self.size) - half_size + 1]
start_index += self.size * self.size

# Right
fake_444.state[50] = self.state[start_index + half_size]
fake_444.state[51] = self.state[start_index + half_size + 1]
fake_444.state[53] = self.state[start_index + (self.size * (half_size-1)) + 1]
fake_444.state[56] = self.state[start_index + (self.size * half_size)]
fake_444.state[57] = self.state[start_index + (self.size * half_size) + 1]
fake_444.state[60] = self.state[start_index + (self.size * (half_size+1))]
fake_444.state[62] = self.state[start_index + (self.size * self.size) - half_size]
fake_444.state[63] = self.state[start_index + (self.size * self.size) - half_size + 1]
start_index += self.size * self.size

# Back
fake_444.state[66] = self.state[start_index + half_size]
fake_444.state[67] = self.state[start_index + half_size + 1]
fake_444.state[69] = self.state[start_index + (self.size * (half_size-1)) + 1]
fake_444.state[72] = self.state[start_index + (self.size * half_size)]
fake_444.state[73] = self.state[start_index + (self.size * half_size) + 1]
fake_444.state[76] = self.state[start_index + (self.size * (half_size+1))]
fake_444.state[78] = self.state[start_index + (self.size * self.size) - half_size]
fake_444.state[79] = self.state[start_index + (self.size * self.size) - half_size + 1]
start_index += self.size * self.size

# Down
fake_444.state[82] = self.state[start_index + half_size]
fake_444.state[83] = self.state[start_index + half_size + 1]
fake_444.state[85] = self.state[start_index + (self.size * (half_size-1)) + 1]
fake_444.state[88] = self.state[start_index + (self.size * half_size)]
fake_444.state[89] = self.state[start_index + (self.size * half_size) + 1]
fake_444.state[92] = self.state[start_index + (self.size * (half_size+1))]
fake_444.state[94] = self.state[start_index + (self.size * self.size) - half_size]
fake_444.state[95] = self.state[start_index + (self.size * self.size) - half_size + 1]
start_index += self.size * self.size

fake_444.group_edges()
#fake_444.print_cube()
#fake_444.print_solution()
half_size_str = str(half_size)

for step in fake_444.solution:

if step == 'EDGES_GROUPED':
continue

# Rotate the entire cube
if step.startswith('4'):
step = str(self.size) + step[1:]

elif step in ("Uw", "Uw'", "Uw2",
"Lw", "Lw'", "Lw2",
"Fw", "Fw'", "Fw2",
"Rw", "Rw'", "Rw2",
"Bw", "Bw'", "Bw2",
"Dw", "Dw'", "Dw2"):
step = half_size_str + step

#log.warning("fake_444 step %s" % step)
self.rotate(step)

#log.info("Inside edges are paired, %d steps in" % self.get_solution_len_minus_rotates(self.solution))

def pair_edge_orbit_via_555(self, orbit):
log.warning("pair_edge_orbit_via_555 for %d" % orbit)
fake_555 = RubiksCube555(solved_5x5x5)
fake_555.lt_init()

# The corners don't matter but it does make troubleshooting easier if they match
start_index = 0
fake_555.state[1] = self.state[start_index+1]
fake_555.state[5] = self.state[start_index + self.size]
fake_555.state[21] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_555.state[25] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

fake_555.state[26] = self.state[start_index+1]
fake_555.state[30] = self.state[start_index + self.size]
fake_555.state[46] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_555.state[50] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

fake_555.state[51] = self.state[start_index+1]
fake_555.state[55] = self.state[start_index + self.size]
fake_555.state[71] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_555.state[75] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

fake_555.state[76] = self.state[start_index+1]
fake_555.state[80] = self.state[start_index + self.size]
fake_555.state[96] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_555.state[100] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

fake_555.state[101] = self.state[start_index+1]
fake_555.state[105] = self.state[start_index + self.size]
fake_555.state[121] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_555.state[125] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

fake_555.state[126] = self.state[start_index+1]
fake_555.state[130] = self.state[start_index + self.size]
fake_555.state[146] = self.state[start_index + (self.size * self.size) - self.size + 1]
fake_555.state[150] = self.state[start_index + (self.size * self.size)]
start_index += self.size * self.size

half_size = int(self.size/2)

# Upper
start_index = 0
fake_555.state[2] = self.state[start_index + orbit + 1]
fake_555.state[3] = self.state[start_index + half_size]
fake_555.state[4] = self.state[start_index + self.size - orbit]

fake_555.state[6] = self.state[start_index + (orbit * self.size) + 1]
fake_555.state[10] = self.state[start_index + (orbit * self.size) + self.size]

# The middle of the edge so orbit doesn't matter
fake_555.state[11] = self.state[start_index + (self.size * (half_size - 1)) + 1]
fake_555.state[15] = self.state[start_index + (self.size * half_size)]

fake_555.state[16] = self.state[start_index + (self.size * self.size) - (orbit * self.size) - self.size + 1]
fake_555.state[20] = self.state[start_index + (self.size * self.size) - (orbit * self.size)]

fake_555.state[22] = self.state[start_index + (self.size * self.size) - self.size + 1 + orbit]
fake_555.state[23] = self.state[start_index + (self.size * self.size) - half_size]
fake_555.state[24] = self.state[start_index + (self.size * self.size) - orbit]
start_index += self.size * self.size


# Left
fake_555.state[27] = self.state[start_index + orbit + 1]
fake_555.state[28] = self.state[start_index + half_size]
fake_555.state[29] = self.state[start_index + self.size - orbit]

fake_555.state[31] = self.state[start_index + (orbit * self.size) + 1]
fake_555.state[35] = self.state[start_index + (orbit * self.size) + self.size]

# The middle of the edge so orbit doesn't matter
fake_555.state[36] = self.state[start_index + (self.size * (half_size - 1)) + 1]
fake_555.state[40] = self.state[start_index + (self.size * half_size)]

fake_555.state[41] = self.state[start_index + (self.size * self.size) - (orbit * self.size) - self.size + 1]
fake_555.state[45] = self.state[start_index + (self.size * self.size) - (orbit * self.size)]

fake_555.state[47] = self.state[start_index + (self.size * self.size) - self.size + 1 + orbit]
fake_555.state[48] = self.state[start_index + (self.size * self.size) - half_size]
fake_555.state[49] = self.state[start_index + (self.size * self.size) - orbit]
start_index += self.size * self.size

# Front
fake_555.state[52] = self.state[start_index + orbit + 1]
fake_555.state[53] = self.state[start_index + half_size]
fake_555.state[54] = self.state[start_index + self.size - orbit]

fake_555.state[56] = self.state[start_index + (orbit * self.size) + 1]
fake_555.state[60] = self.state[start_index + (orbit * self.size) + self.size]

# The middle of the edge so orbit doesn't matter
fake_555.state[61] = self.state[start_index + (self.size * (half_size - 1)) + 1]
fake_555.state[65] = self.state[start_index + (self.size * half_size)]

fake_555.state[66] = self.state[start_index + (self.size * self.size) - (orbit * self.size) - self.size + 1]
fake_555.state[70] = self.state[start_index + (self.size * self.size) - (orbit * self.size)]

fake_555.state[72] = self.state[start_index + (self.size * self.size) - self.size + 1 + orbit]
fake_555.state[73] = self.state[start_index + (self.size * self.size) - half_size]
fake_555.state[74] = self.state[start_index + (self.size * self.size) - orbit]
start_index += self.size * self.size

# Right
fake_555.state[77] = self.state[start_index + orbit + 1]
fake_555.state[78] = self.state[start_index + half_size]
fake_555.state[79] = self.state[start_index + self.size - orbit]

fake_555.state[81] = self.state[start_index + (orbit * self.size) + 1]
fake_555.state[85] = self.state[start_index + (orbit * self.size) + self.size]

# The middle of the edge so orbit doesn't matter
fake_555.state[86] = self.state[start_index + (self.size * (half_size - 1)) + 1]
fake_555.state[90] = self.state[start_index + (self.size * half_size)]

fake_555.state[91] = self.state[start_index + (self.size * self.size) - (orbit * self.size) - self.size + 1]
fake_555.state[95] = self.state[start_index + (self.size * self.size) - (orbit * self.size)]

fake_555.state[97] = self.state[start_index + (self.size * self.size) - self.size + 1 + orbit]
fake_555.state[98] = self.state[start_index + (self.size * self.size) - half_size]
fake_555.state[99] = self.state[start_index + (self.size * self.size) - orbit]
start_index += self.size * self.size

# Back
fake_555.state[102] = self.state[start_index + orbit + 1]
fake_555.state[103] = self.state[start_index + half_size]
fake_555.state[104] = self.state[start_index + self.size - orbit]

fake_555.state[106] = self.state[start_index + (orbit * self.size) + 1]
fake_555.state[110] = self.state[start_index + (orbit * self.size) + self.size]

# The middle of the edge so orbit doesn't matter
fake_555.state[111] = self.state[start_index + (self.size * (half_size - 1)) + 1]
fake_555.state[115] = self.state[start_index + (self.size * half_size)]

fake_555.state[116] = self.state[start_index + (self.size * self.size) - (orbit * self.size) - self.size + 1]
fake_555.state[120] = self.state[start_index + (self.size * self.size) - (orbit * self.size)]

fake_555.state[122] = self.state[start_index + (self.size * self.size) - self.size + 1 + orbit]
fake_555.state[123] = self.state[start_index + (self.size * self.size) - half_size]
fake_555.state[124] = self.state[start_index + (self.size * self.size) - orbit]
start_index += self.size * self.size


# Down
fake_555.state[127] = self.state[start_index + orbit + 1]
fake_555.state[128] = self.state[start_index + half_size]
fake_555.state[129] = self.state[start_index + self.size - orbit]

fake_555.state[131] = self.state[start_index + (orbit * self.size) + 1]
fake_555.state[135] = self.state[start_index + (orbit * self.size) + self.size]

# The middle of the edge so orbit doesn't matter
fake_555.state[136] = self.state[start_index + (self.size * (half_size - 1)) + 1]
fake_555.state[140] = self.state[start_index + (self.size * half_size)]

fake_555.state[141] = self.state[start_index + (self.size * self.size) - (orbit * self.size) - self.size + 1]
fake_555.state[145] = self.state[start_index + (self.size * self.size) - (orbit * self.size)]

fake_555.state[147] = self.state[start_index + (self.size * self.size) - self.size + 1 + orbit]
fake_555.state[148] = self.state[start_index + (self.size * self.size) - half_size]
fake_555.state[149] = self.state[start_index + (self.size * self.size) - orbit]
start_index += self.size * self.size

self.print_cube()
fake_555.print_cube()
#sys.exit(0)
fake_555.avoid_pll = False
fake_555.group_edges()

# dwalton
wide_str = str(orbit + 1)
for step in fake_555.solution:

if step == 'EDGES_GROUPED':
continue

# Rotate the entire cube
if step.startswith('5'):
step = str(self.size) + step[1:]

elif step in ("Uw", "Uw'", "Uw2",
"Lw", "Lw'", "Lw2",
"Fw", "Fw'", "Fw2",
"Rw", "Rw'", "Rw2",
"Bw", "Bw'", "Bw2",
"Dw", "Dw'", "Dw2"):
step = wide_str + step

#log.warning("fake_555 step %s" % step)
self.rotate(step)

def group_edges(self):

if not self.get_non_paired_edges():