Project

General

Profile

« Previous | Next » 

Revision 6bd1dc64

Added by Leszek Koltunski 9 months ago

Progress with PhasedSolver.
Introduce an abstracted TargetQuats.

View differences:

src/main/java/org/distorted/objectlib/algphases/Phase.java
11 11

  
12 12
import org.distorted.objectlib.algsolvers.MitmTable;
13 13
import org.distorted.objectlib.algsolvers.SolvedObject;
14
import org.distorted.objectlib.algsolvers.TargetQuats;
14 15

  
15 16
///////////////////////////////////////////////////////////////////////////////////////////////////
16 17

  
......
20 21

  
21 22
  protected int[][] mCubitGroups;
22 23
  protected int mNumGroups;
24
  protected int mNumCubitsInThisPhase;
23 25
  protected int mNumCubits;
24
  protected int[][] mEndQuats;
26
  protected TargetQuats mTargetQuats;
27

  
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29

  
30
  Phase(SolvedObject object)
31
    {
32
    float[][] pos = object.getCubitPositions();
33
    mNumCubits = pos.length;
34
    }
25 35

  
26 36
///////////////////////////////////////////////////////////////////////////////////////////////////
27 37

  
......
41 51
  public int whichSubPhase(int cubit)
42 52
    {
43 53
    for(int g=0; g<mNumGroups; g++)
44
      for( int j : mCubitGroups[g])
54
      for(int j : mCubitGroups[g])
45 55
        if( cubit==j ) return g;
46 56

  
47 57
    return -1;
......
49 59

  
50 60
///////////////////////////////////////////////////////////////////////////////////////////////////
51 61

  
52
  public int[] endQuatIndices(SolvedObject object, int cubitQuat, int cubit)
62
  public int[] endQuatIndices(SolvedObject object, int cubit)
53 63
    {
54 64
    return INDICES;
55 65
    }
56 66

  
57 67
///////////////////////////////////////////////////////////////////////////////////////////////////
58 68

  
59
  public void setEndQuats(int[][] endquats)
69
  public void setTargetQuats(SolvedObject object, boolean[] inPreviousPhases)
60 70
    {
61
    mEndQuats = endquats;
62
    }
71
    int len = inPreviousPhases.length;
63 72

  
64
///////////////////////////////////////////////////////////////////////////////////////////////////
73
    int[][] target = new int[len][];
65 74

  
66
  public int[][] getEndQuats()
67
    {
68
    return mEndQuats;
75
    for(int c=0; c<len; c++)
76
      {
77
      if( inPreviousPhases[c] ) target[c] = INDICES;
78
      else if( contains(c) )    target[c] = endQuatIndices(object,c);
79
      else                      target[c] = null;
80
      }
81

  
82
    mTargetQuats = new TargetQuats(target);
69 83
    }
70 84

  
71 85
///////////////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/objectlib/algphases/PhaseCyclicOrie1.java
23 23

  
24 24
  public PhaseCyclicOrie1(SolvedObject object, int cubit, int quat)
25 25
    {
26
    super(object);
27

  
26 28
    Static4D[] objectQuats = object.getQuats();
27 29
    Static4D q = objectQuats[quat];
28 30
    double alpha = 2*Math.acos(q.get3());
29 31
    double numTurns = 2*Math.PI / alpha;
30
    mNumCubits = (int)(numTurns+0.5f);
32
    mNumCubitsInThisPhase = (int)(numTurns+0.5f);
31 33

  
32
    mCubitGroups  = new int[1][mNumCubits];
34
    mCubitGroups  = new int[1][mNumCubitsInThisPhase];
33 35
    mNumGroups = 1;
34 36
    mCyclicQuat = quat;
35 37

  
......
43 45

  
44 46
    mCubitGroups[0][0] = cubit;
45 47

  
46
    for(int c=1; c<mNumCubits; c++)
48
    for(int c=1; c<mNumCubitsInThisPhase; c++)
47 49
      {
48 50
      QuatHelper.rotateVectorByQuat(tmp,x,y,z,1,q);
49 51
      x = tmp[0];
......
84 86
///////////////////////////////////////////////////////////////////////////////////////////////////
85 87

  
86 88
  @Override
87
  public int[] endQuatIndices(SolvedObject object, int cubitQuat, int cubit)
89
  public int[] endQuatIndices(SolvedObject object, int cubit)
88 90
    {
89
    int[] retQuats = new int[mNumCubits];
91
    int[] retQuats = new int[mNumCubitsInThisPhase];
90 92
    retQuats[0] = 0;
91 93
    retQuats[1] = mCyclicQuat;
92 94

  
93
    for(int i=2; i<mNumCubits; i++)
95
    for(int i=2; i<mNumCubitsInThisPhase; i++)
94 96
      {
95 97
      retQuats[i] = object.getMultQuat(mCyclicQuat,retQuats[i-1]);
96 98
      }
src/main/java/org/distorted/objectlib/algphases/PhaseCyclicOrie2.java
19 19
{
20 20
  public PhaseCyclicOrie2(SolvedObject object, int cubit, int quat)
21 21
    {
22
    super(object);
23

  
22 24
    Static4D[] objectQuats = object.getQuats();
23 25
    Static4D q = objectQuats[quat];
24 26
    double alpha = 2*Math.acos(q.get3());
25 27
    double numTurns = 2*Math.PI / alpha;
26
    mNumCubits = (int)(numTurns+0.5f);
28
    mNumCubitsInThisPhase = (int)(numTurns+0.5f);
27 29

  
28
    mCubitGroups  = new int[1][mNumCubits];
30
    mCubitGroups  = new int[1][mNumCubitsInThisPhase];
29 31
    mNumGroups = 1;
30 32

  
31 33
    float[][] positions = object.getCubitPositions();
......
38 40

  
39 41
    mCubitGroups[0][0] = cubit;
40 42

  
41
    for(int c=1; c<mNumCubits; c++)
43
    for(int c=1; c<mNumCubitsInThisPhase; c++)
42 44
      {
43 45
      QuatHelper.rotateVectorByQuat(tmp,x,y,z,1,q);
44 46
      x = tmp[0];
src/main/java/org/distorted/objectlib/algphases/PhaseCyclicPerm1.java
24 24

  
25 25
  public PhaseCyclicPerm1(SolvedObject object, int cubit, int quat)
26 26
    {
27
    super(object);
28

  
27 29
    Static4D[] objectQuats = object.getQuats();
28 30
    Static4D q = objectQuats[quat];
29 31
    double alpha = 2*Math.acos(q.get3());
30 32
    double numTurns = 2*Math.PI / alpha;
31
    mNumCubits = (int)(numTurns+0.5f);
33
    mNumCubitsInThisPhase = (int)(numTurns+0.5f);
32 34

  
33
    mCubitGroups  = new int[1][mNumCubits];
35
    mCubitGroups  = new int[1][mNumCubitsInThisPhase];
34 36
    mNumGroups = 1;
35 37
    mObjectQuats = objectQuats;
36 38

  
......
45 47

  
46 48
    mCubitGroups[0][0] = cubit;
47 49

  
48
    for(int c=1; c<mNumCubits; c++)
50
    for(int c=1; c<mNumCubitsInThisPhase; c++)
49 51
      {
50 52
      QuatHelper.rotateVectorByQuat(tmp,x,y,z,1,q);
51 53
      x = tmp[0];
......
86 88
///////////////////////////////////////////////////////////////////////////////////////////////////
87 89

  
88 90
  @Override
89
  public int[] endQuatIndices(SolvedObject object, int cubitQuat, int cubit)
91
  public int[] endQuatIndices(SolvedObject object, int cubit)
90 92
    {
91 93
    float[] thisPos = mPositions[cubit];
92 94
    int numQuats = mObjectQuats.length;
......
100 102

  
101 103
    for(int q=0; q<numQuats; q++)
102 104
      {
103
      int qn = object.getMultQuat(q,cubitQuat);  // i.e. if we first rotate cubit by cubitQuat then it ends
104
                                                 // up in (x,y,z) (current position) and then by q and it
105
                                                 // ends up in final pos (but not necessarily final orientation)
106
      QuatHelper.rotateVectorByQuat(tmp,x,y,z,1,mObjectQuats[qn]);
105
      QuatHelper.rotateVectorByQuat(tmp,x,y,z,1,mObjectQuats[q]);
107 106

  
108 107
      float dx = tmp[0] - x;
109 108
      float dy = tmp[1] - y;
......
113 112
      if( err < MAX_ERROR )
114 113
        {
115 114
        numGoodQuats++;
116
        tmpQuats[qn] = 1;
115
        tmpQuats[q] = 1;
117 116
        }
118 117
      }
119 118

  
src/main/java/org/distorted/objectlib/algphases/PhaseCyclicPerm2.java
19 19
{
20 20
  public PhaseCyclicPerm2(SolvedObject object, int cubit, int quat)
21 21
    {
22
    super(object);
23

  
22 24
    Static4D[] objectQuats = object.getQuats();
23 25
    Static4D q = objectQuats[quat];
24 26
    double alpha = 2*Math.acos(q.get3());
25 27
    double numTurns = 2*Math.PI / alpha;
26
    mNumCubits = (int)(numTurns+0.5f);
28
    mNumCubitsInThisPhase = (int)(numTurns+0.5f);
27 29

  
28
    mCubitGroups  = new int[1][mNumCubits];
30
    mCubitGroups  = new int[1][mNumCubitsInThisPhase];
29 31
    mNumGroups = 1;
30 32

  
31 33
    float[][] positions = object.getCubitPositions();
......
38 40

  
39 41
    mCubitGroups[0][0] = cubit;
40 42

  
41
    for(int c=1; c<mNumCubits; c++)
43
    for(int c=1; c<mNumCubitsInThisPhase; c++)
42 44
      {
43 45
      QuatHelper.rotateVectorByQuat(tmp,x,y,z,1,q);
44 46
      x = tmp[0];
src/main/java/org/distorted/objectlib/algphases/PhaseMitm.java
11 11

  
12 12
import org.distorted.objectlib.algsolvers.MitmTable;
13 13
import org.distorted.objectlib.algsolvers.SolvedObject;
14
import org.distorted.objectlib.algsolvers.TargetQuats;
14 15

  
15 16
///////////////////////////////////////////////////////////////////////////////////////////////////
16 17

  
......
20 21
  private final static double MAX_SEARCH = 10000000.0;   // max 10mln positions back-searched
21 22

  
22 23
  private boolean[] mSolved;
23
  private int[][] mTmp;
24 24
  private int[] mWhichSubphase;
25 25
  private int mForwardDepth, mBackwardDepth;
26
  private int mDepth;
26
  private int mDepth, mGroup;
27

  
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29

  
30
  PhaseMitm(SolvedObject object)
31
    {
32
    super(object);
33
    }
27 34

  
28 35
///////////////////////////////////////////////////////////////////////////////////////////////////
29 36
// Only attempt to find solutions which are not longer than maxlen; if not found, return null.
......
43 50
    int tmpBackward= depth-tmpForward;
44 51

  
45 52
    table.build(object,tmpForward);
46
    return table.tryReaching(object,mEndQuats,tmpBackward,tmpForward);
53
    return table.tryReaching(object,mTargetQuats,tmpBackward,tmpForward);
47 54
    }
48 55

  
49 56
///////////////////////////////////////////////////////////////////////////////////////////////////
50 57

  
51 58
  private int prepareForSubPhase(SolvedObject object, MitmTable table)
52 59
    {
53
    table.prepareForSubPhase(mEndQuats);
60
    table.prepareForSubPhase(mTargetQuats);
54 61
    int bytesPerEntry = table.getBytesPerEntry();
55 62
    int branchingFactor = object.getBranchingFactor();
56 63

  
......
75 82

  
76 83
  private int computeBackwardDepth(int branchingFactor)
77 84
    {
78
    int multiplier = 1;
79

  
80
    for( int[] quats : mEndQuats )
81
      if( quats!=null ) multiplier *= quats.length;
82

  
85
    int multiplier = mTargetQuats.computeNumCombinations();
83 86
    double maxDepth = Math.log(MAX_SEARCH/multiplier) / Math.log(branchingFactor);
84

  
85 87
    return (int)maxDepth;
86 88
    }
87 89

  
......
106 108
  @Override
107 109
  public void prepareForSubphases()
108 110
    {
109
    int numEndQuats = mEndQuats.length;
110 111
    mSolved = new boolean[mNumGroups];
111
    mTmp = new int[numEndQuats][];
112
    mWhichSubphase = new int[numEndQuats];
112
    mWhichSubphase = new int[mNumCubits];
113 113

  
114
    for(int c=0; c<numEndQuats; c++) mWhichSubphase[c] = whichSubPhase(c);
114
    for(int c=0; c<mNumCubits; c++) mWhichSubphase[c] = whichSubPhase(c);
115 115
    for(int s=0; s<mNumGroups; s++) mSolved[s] = false;
116 116
    mDepth = 0;
117
    mGroup = 0;
117 118
    }
118 119

  
119 120
///////////////////////////////////////////////////////////////////////////////////////////////////
......
150 151
///////////////////////////////////////////////////////////////////////////////////////////////////
151 152

  
152 153
  @Override
153
  public boolean solveAnySubphase( SolvedObject object, MitmTable table, int[][] solution, int solIndex)
154
  public boolean solveAnySubphase( SolvedObject object, MitmTable table, int[][] solution, int subPhase)
154 155
    {
155
    int maxDepth = mDepth;
156
    int numQuats = mEndQuats.length;
157
    System.arraycopy(mEndQuats, 0, mTmp, 0, numQuats);
156
    int maxDepth = mDepth+1;  // this might mean that we do one extra depth, but if we set it to
157
                              // mDepth then if after current mGroups there are no more unsolved
158
                              // subgroups, we will simply give up and end solving altogether!
159

  
160
    TargetQuats tmp = new TargetQuats(mTargetQuats);
158 161

  
159
    for( ; mDepth<=maxDepth; mDepth++)
160
      for(int p=0; p<mNumGroups; p++)
161
        if( !mSolved[p] )
162
    for( ; mDepth<=maxDepth; mDepth++,mGroup=0)
163
      for(int g=mGroup; g<mNumGroups; g++)
164
        if( !mSolved[g] )
162 165
          {
163
          for(int q=0; q<numQuats; q++)
166
          for(int q=0; q<mNumCubits; q++)
164 167
            {
165
            // -1 means that the cubit belongs to the previous (or next) phase. Cubits belonging to the
166
            // next phase already have their endQuats set to null (see PhasedSolver.figureOutEndQuatIndices)
167
            // Here we set to null (i.e. - mark that we do not care about) the quats of all cubits which
168
            // -1 means that the cubit doesn't belong to the current phase. Cubits belonging to
169
            // the next phase already have their targetQuats set to null (see Phase.setTargetQuats)
170
            // Here we set to null (mark that we do not care about) the quats of all cubits which
168 171
            // belong to the current phase and haven't been solved yet (except the current subphase!).
169
            int sp = mWhichSubphase[q];
170
            mEndQuats[q] = (sp==-1 || sp==p || mSolved[sp]) ? mTmp[q] : null;
172
            int wsp = mWhichSubphase[q];
173
            int[] newValue = (wsp==-1 || wsp==g || mSolved[wsp]) ? tmp.getQuat(q) : null;
174
            mTargetQuats.setQuat(newValue,q);
171 175
            }
172 176
          maxDepth = prepareForSubPhase(object,table);
173
          solution[solIndex] = findSol(object,table,mDepth);
177
          solution[subPhase] = findSol(object,table,mDepth);
174 178

  
175
          if( solution[solIndex]!=null )
179
          if( solution[subPhase]!=null )
176 180
            {
177
            System.arraycopy(mTmp, 0, mEndQuats, 0, numQuats);
178
            mSolved[p] = true;
181
            mTargetQuats.set(tmp);
182
            mSolved[g] = true;
183
            mGroup = g+1;   // when we get called next time, do not repeat the calculations
179 184
            return true;
180 185
            }
181 186
          }
182 187

  
183
    System.arraycopy(mTmp, 0, mEndQuats, 0, numQuats);
188
    mTargetQuats.set(tmp);
184 189
    return false;
185 190
    }
186 191
}
src/main/java/org/distorted/objectlib/algphases/PhaseNotCyclic.java
9 9

  
10 10
package org.distorted.objectlib.algphases;
11 11

  
12
import org.distorted.objectlib.algsolvers.SolvedObject;
13

  
12 14
///////////////////////////////////////////////////////////////////////////////////////////////////
13 15

  
14 16
public class PhaseNotCyclic extends PhaseMitm
15 17
{
16
  public PhaseNotCyclic(int[][] cubitgroups)
18
  public PhaseNotCyclic(SolvedObject object, int[][] cubitgroups)
17 19
    {
20
    super(object);
21

  
18 22
    mCubitGroups = cubitgroups;
19 23
    mNumGroups = cubitgroups.length;
20 24

  
21 25
    int numCubits = 0;
22 26
    for(int g=0; g<mNumGroups; g++) numCubits += mCubitGroups[g].length;
23 27

  
24
    mNumCubits = numCubits;
28
    mNumCubitsInThisPhase = numCubits;
25 29
    }
26 30
}
src/main/java/org/distorted/objectlib/algphases/PhaseRegex.java
12 12
import org.distorted.objectlib.algsolvers.MitmTable;
13 13
import org.distorted.objectlib.algsolvers.MoveRegex;
14 14
import org.distorted.objectlib.algsolvers.SolvedObject;
15
import org.distorted.objectlib.algsolvers.TargetQuats;
15 16

  
16 17
///////////////////////////////////////////////////////////////////////////////////////////////////
17 18

  
......
29 30

  
30 31
  public PhaseRegex(SolvedObject object, String regex, int[][] cubitgroups)
31 32
    {
33
    super(object);
34

  
32 35
    mCubitGroups = cubitgroups;
33 36
    mNumGroups = cubitgroups.length;
34 37
    mRegex = new MoveRegex(object,regex);
......
38 41
    int numCubits = 0;
39 42
    for(int g=0; g<mNumGroups; g++) numCubits += mCubitGroups[g].length;
40 43

  
41
    mNumCubits = numCubits;
44
    mNumCubitsInThisPhase = numCubits;
42 45

  
43 46
    mSolved = new boolean[mNumGroups];
44 47
    }
45 48

  
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

  
48
  private boolean quatsMatchEndQuats(int[] quats)
49
    {
50
    int numQuats = quats.length;
51

  
52
    for(int q=0; q<numQuats; q++)
53
      {
54
      int[] eq = mEndQuats[q];
55
      if( eq!=null && doesntMatch(quats[q],eq) ) return false;
56
      }
57

  
58
    return true;
59
    }
60

  
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

  
63
  private boolean doesntMatch(int quat, int[] endquats)
64
    {
65
    for(int endquat : endquats)
66
      if( quat==endquat ) return false;
67

  
68
    return true;
69
    }
70

  
71 49
///////////////////////////////////////////////////////////////////////////////////////////////////
72 50

  
73 51
  private int findMove(int ax, int row, int angle)
......
165 143

  
166 144
  public void prepareForSubphases()
167 145
    {
168
    int numEndQuats = mEndQuats.length;
169
    mTmp = new int[numEndQuats][];
170
    mWhichSubphase = new int[numEndQuats];
146
    mTmp = new int[mNumCubits][];
147
    mWhichSubphase = new int[mNumCubits];
171 148

  
172
    for(int c=0; c<numEndQuats; c++) mWhichSubphase[c] = whichSubPhase(c);
149
    for(int c=0; c<mNumCubits; c++) mWhichSubphase[c] = whichSubPhase(c);
173 150
    for(int s=0; s<mNumGroups; s++) mSolved[s] = false;
174 151
    }
175 152

  
......
186 163
      int numMoves = (moveSeq==null ? 0 : moveSeq.length);
187 164
      for(int m=1; m<numMoves; m++) object.makeMove(moveSeq[m]);
188 165
      int[] qts = object.getCubitQuats();
189
      boolean solved = quatsMatchEndQuats(qts);
166
      boolean solved = mTargetQuats.matchesQuats(qts);
190 167
      object.setUpStartingQuats(quats);
191 168
      if( solved ) return simplify(moveSeq);
192 169
      moveSeq = mRegex.getNext();
......
200 177

  
201 178
  public boolean solveAnySubphase(SolvedObject object, MitmTable table, int[][] solution, int solIndex)
202 179
    {
203
    int numQuats = mEndQuats.length;
204
    System.arraycopy(mEndQuats, 0, mTmp, 0, numQuats);
180
    TargetQuats tmp = new TargetQuats(mTargetQuats);
205 181

  
206 182
    for(int p=0; p<mNumGroups; p++)
207 183
      if( !mSolved[p] )
208 184
        {
209
        for(int q=0; q<numQuats; q++)
185
        for(int q=0; q<mNumCubits; q++)
210 186
          {
211 187
          // -1 means that the cubit belongs to the previous (or next) phase. Cubits belonging to the
212 188
          // next phase already have their endQuats set to null (see PhasedSolver.figureOutEndQuatIndices)
213 189
          // Here we set to null (i.e. - mark that we do not care about) the quats of all cubits which
214 190
          // belong to the current phase and haven't been solved yet (except the current subphase!).
215 191
          int sp = mWhichSubphase[q];
216
          mEndQuats[q] = (sp==-1 || sp==p || mSolved[sp]) ? mTmp[q] : null;
192
          int[] newValue = (sp==-1 || sp==p || mSolved[sp]) ? mTmp[q] : null;
193
          mTargetQuats.setQuat(newValue,q);
217 194
          }
218 195

  
219 196
        solution[solIndex] = findSolution(object,table);
220 197

  
221 198
        if( solution[solIndex]!=null )
222 199
          {
223
          System.arraycopy(mTmp, 0, mEndQuats, 0, numQuats);
200
          mTargetQuats.set(tmp);
224 201
          mSolved[p] = true;
225 202
          return true;
226 203
          }
227 204
        }
228 205

  
229
    System.arraycopy(mTmp, 0, mEndQuats, 0, numQuats);
206
    mTargetQuats.set(tmp);
230 207
    return false;
231 208
    }
232 209
}
src/main/java/org/distorted/objectlib/algsolvers/MitmTable.java
124 124

  
125 125
///////////////////////////////////////////////////////////////////////////////////////////////////
126 126

  
127
  public void prepareForSubPhase(int[][] endQuats)
127
  public void prepareForSubPhase(TargetQuats quats)
128 128
    {
129
    int numUsedCubits = 0;
130

  
131
    for(int e=0; e<mNumCubits; e++)
132
      {
133
      if( endQuats[e]!=null )
134
        {
135
        numUsedCubits++;
136
        mUseCubit[e] = true;
137
        }
138
      else
139
        {
140
        mUseCubit[e] = false;
141
        }
142
      }
143

  
129
    int numUsedCubits = quats.computeUsedCubitTable(mUseCubit);
144 130
    double numBytes = numUsedCubits*mBitsPerQuat/8.0;
145 131
    mBytesPerEntry = (int)Math.ceil(numBytes);  // this many bytes will be needed to store one position
146 132
    mBuildDepth = -1;
......
169 155
// {0} means solution found and it's empty (position already solved)
170 156
// {2,1,3} means the solution is 2 moves long, and the indices of moves to make are 1 and 3.
171 157

  
172
  public int[] tryReaching(SolvedObject object, int[][] endQuats, int lenb, int lenf)
158
  public int[] tryReaching(SolvedObject object, TargetQuats target, int lenb, int lenf)
173 159
    {
174
    int[] indices = new int[mNumCubits];
175
    boolean thereIsNext;
176 160
    int branching = object.getBranchingFactor();
177 161
    int[] backward = new int[lenb];
178 162
    int[] rem = object.getCopiedCubitQuats();
163
    int[] quats = target.getFirst();
179 164

  
180 165
    do
181 166
      {
182
      object.setUpStartingQuats(endQuats,indices);
167
      object.setUpStartingQuats(quats);
183 168
      byte[] reached = tryReachingRecursive(object,branching,lenb,backward);
184 169

  
185 170
      if( reached!=null )
......
190 175
        return joinSequences(forward,numMoves,backward);
191 176
        }
192 177

  
193
      thereIsNext = getNext(endQuats,indices);
178
      quats = target.getNext();
194 179
      }
195
    while( thereIsNext );
180
    while( quats!=null );
196 181

  
197 182
    object.setUpStartingQuats(rem);
198 183
    return null;
......
337 322
          }
338 323
    }
339 324

  
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341

  
342
  private boolean getNext(int[][] quats, int[] indices)
343
    {
344
    for(int i=indices.length-1; i>=0; i--)
345
      {
346
      int[] q = quats[i];
347
      int len = q!=null ? q.length-1 : 0;
348

  
349
      if( indices[i]<len )
350
        {
351
        indices[i]++;
352
        return true;
353
        }
354
      }
355

  
356
    return false;
357
    }
358

  
359 325
///////////////////////////////////////////////////////////////////////////////////////////////////
360 326
// Find index'th entry in the table 'output'; it contains 8 bits. Write 'value' to it, but only
361 327
// its 'toBeWritten' first bits (out of the 'remaining' bits), and at offset 'offset' in the table.
src/main/java/org/distorted/objectlib/algsolvers/PhasedSolver.java
16 16

  
17 17
public class PhasedSolver
18 18
{
19
  private static final int[] INDICES = {0};
20

  
21 19
  private final Phase[] mPhases;
22 20
  private final SolvedObject mObject;
23 21
  private final MitmTable mTable;
......
58 56

  
59 57
  int[] findSolutionSubphases(Phase phase, int numSubphases)
60 58
    {
61
    int solIndex=0;
62
    int[][] endQuats = phase.getEndQuats();
63
    int numEndQuats = endQuats.length;
64
    int[][] solution = new int[numEndQuats][];
59
    int subPhase=0;
60
    int[][] solution = new int[numSubphases][];
65 61

  
66 62
    phase.prepareForSubphases();
67 63

  
68
    for(; solIndex<numSubphases; solIndex++)
69
      if( !phase.solveAnySubphase(mObject,mTable,solution,solIndex) )
64
    for(; subPhase<numSubphases; subPhase++)
65
      if( !phase.solveAnySubphase(mObject,mTable,solution,subPhase) )
70 66
        {
71
        System.out.println("findSolutionSubphases: failed to solve subphase "+solIndex);
67
        System.out.println("findSolutionSubphases: failed to solve subphase "+subPhase);
72 68
        break;
73 69
        }
74 70

  
75
    if( solIndex>0 )
71
    if( subPhase>0 )
76 72
      {
77 73
      int index=1, num=1;
78
      for(int i=0; i<solIndex; i++) num += (solution[i].length-1);
74
      for(int i=0; i<subPhase; i++) num += (solution[i].length-1);
79 75

  
80 76
      int[] ret = new int[num];
81 77
      ret[0] = num-1;
82 78

  
83
      for(int i=0; i<solIndex; i++)
79
      for(int i=0; i<subPhase; i++)
84 80
        {
85 81
        int len = solution[i].length;
86 82
        for(int j=1; j<len; j++) ret[index++] = solution[i][j];
......
94 90

  
95 91
///////////////////////////////////////////////////////////////////////////////////////////////////
96 92

  
97
  private int[] figureOutEndQuatIndices(int cubitQuat, int phase, int cubit)
93
  private int[] solutionOfPhase(int currentPhase)
98 94
    {
99
    for(int p=0; p<phase; p++)
100
      if( mPhases[p].contains(cubit) ) return INDICES;
101

  
102
    if( mPhases[phase].contains(cubit) )
103
      return mPhases[phase].endQuatIndices(mObject,cubitQuat,cubit);
104

  
105
    return null;
106
    }
107

  
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109
// quats get overwritten at the end of the phase
110
// return null on error
111

  
112
  private int[] solutionOfPhase(int phase, int[] quats)
113
    {
114
    Phase p = mPhases[phase];
115
    int numSubphases = p.numSubphases();
116 95
    int numCubits = mPositions.length;
117
    int[][] endQuats = new int[numCubits][];
96
    boolean[] previousPhases = new boolean[numCubits];
118 97

  
119 98
    for(int c=0; c<numCubits; c++)
120
      {
121
      endQuats[c] = figureOutEndQuatIndices(quats[c],phase,c);
122
      }
99
      for(int p=0; p<currentPhase; p++)
100
        if( mPhases[p].contains(c) )
101
          {
102
          previousPhases[c] = true;
103
          break;
104
          }
123 105

  
124
    p.setEndQuats(endQuats);
106
    Phase phase = mPhases[currentPhase];
107
    int numSubphases = phase.numSubphases();
108
    phase.setTargetQuats(mObject,previousPhases);
125 109

  
126 110
    if( numSubphases>1 )
127 111
      {
128
      return findSolutionSubphases(p,numSubphases);
112
      return findSolutionSubphases(phase,numSubphases);
129 113
      }
130 114
    else
131 115
      {
132
      return p.findSolution(mObject,mTable);
116
      return phase.findSolution(mObject,mTable);
133 117
      }
134 118
    }
135 119

  
......
143 127
    int[][] solution_moves = new int[mNumPhases][];
144 128
    prepareForSolution(quats);
145 129

  
146
    for(int i=0; i<mNumPhases; i++)
130
    for(int p=0; p<mNumPhases; p++)
147 131
      {
148
      solution_moves[i] = solutionOfPhase(i,quats);
132
      solution_moves[p] = solutionOfPhase(p);
149 133

  
150
      if( solution_moves[i]==null )
134
      if( solution_moves[p]==null )
151 135
        {
152
        System.out.println("AlgSolver: error solving phase "+i);
136
        System.out.println("AlgSolver: error solving phase "+p);
153 137
        break;
154 138
        }
155 139
      else
156 140
        {
157 141
        long next = System.currentTimeMillis();
158
        System.out.println("AlgSolver: phase "+i+" solution len: "+solution_moves[i][0]+" time: "+(next-millis));
142
        System.out.println("AlgSolver: phase "+p+" solution len: "+solution_moves[p][0]+" time: "+(next-millis));
159 143
        millis = next;
160 144
        }
161 145
      }
src/main/java/org/distorted/objectlib/algsolvers/SolvedObject.java
69 69
///////////////////////////////////////////////////////////////////////////////////////////////////
70 70

  
71 71
  public void setUpStartingQuats(int[] quats)                  { mCubits.setUpQuats(quats); }
72
  public void setUpStartingQuats(int[][] quats, int[] indices) { mCubits.setUpQuats(quats,indices); }
73 72
  public void makeMove(int moveIndex)                          { mCubits.makeMove(moveIndex); }
74 73
  public void backMove(int moveIndex)                          { mCubits.backMove(moveIndex); }
75 74
  public int[] getCubitQuats()                                 { return mCubits.getRotQuats(); }
src/main/java/org/distorted/objectlib/algsolvers/SolvedObjectCubit.java
119 119
    for(int c=0; c<mNumCubits; c++) mRotQuats[c] = quats[c];
120 120
    }
121 121

  
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123
// here we set the indices of cubits we don't care about at the moment to -1.
124

  
125
  void setUpQuats(int[][] quats, int[] indices)
126
    {
127
    for(int c=0; c<mNumCubits; c++)
128
      {
129
      int[] q = quats[c];
130
      mRotQuats[c] = q!=null ? q[indices[c]] : -1;
131
      }
132
    }
133

  
134 122
///////////////////////////////////////////////////////////////////////////////////////////////////
135 123

  
136 124
  int[] getRotQuats()
src/main/java/org/distorted/objectlib/algsolvers/TargetQuats.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2024 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

  
10
package org.distorted.objectlib.algsolvers;
11

  
12
public class TargetQuats
13
{
14
  private final int[][] mEndQuats;
15
  private final int[] mTmp;
16
  private final int[] mIndices;
17

  
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
  public TargetQuats(int[][] endQuats)
21
    {
22
    int len = endQuats.length;
23
    mEndQuats = endQuats;
24
    mTmp = new int[len];
25
    mIndices = new int[len];
26
    }
27

  
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29

  
30
  public TargetQuats(TargetQuats source)
31
    {
32
    int len = source.mEndQuats.length;
33
    mEndQuats = new int[len][];
34
    System.arraycopy(source.mEndQuats,0,mEndQuats,0,len);
35
    mTmp = new int[len];
36
    mIndices = new int[len];
37
    }
38

  
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

  
41
  public String debug()
42
    {
43
    return MitmTable.getMultiQuatString(mEndQuats);
44
    }
45

  
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

  
48
  public void set(TargetQuats source)
49
    {
50
    int len = mEndQuats.length;
51
    System.arraycopy(source.mEndQuats,0,mEndQuats,0,len);
52
    }
53

  
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55

  
56
  public void setQuat(int[] source, int quat)
57
    {
58
    mEndQuats[quat] = source;
59
    }
60

  
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

  
63
  public int[] getQuat(int quat)
64
    {
65
    return mEndQuats[quat];
66
    }
67

  
68
///////////////////////////////////////////////////////////////////////////////////////////////////
69
// how many combinations are we going to have to start from when reachingBack to the MitmTable?
70

  
71
  public int computeNumCombinations()
72
    {
73
    int num = 1;
74

  
75
    for( int[] quats : mEndQuats )
76
      if( quats!=null ) num *= quats.length;
77

  
78
    return num;
79
    }
80

  
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82

  
83
  public int computeUsedCubitTable(boolean[] table)
84
    {
85
    int len = mEndQuats.length;
86
    int numUsedCubits = 0;
87

  
88
    for(int e=0; e<len; e++)
89
      {
90
      if( mEndQuats[e]!=null )
91
        {
92
        numUsedCubits++;
93
        table[e] = true;
94
        }
95
      else
96
        {
97
        table[e] = false;
98
        }
99
      }
100

  
101
    return numUsedCubits;
102
    }
103

  
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105

  
106
  public int[] getFirst()
107
    {
108
    int len = mEndQuats.length;
109
    for(int q=0; q<len; q++) mIndices[q] = 0;
110
    return getCurrent();
111
    }
112

  
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114

  
115
  public int[] getNext()
116
    {
117
    if( incIndices() ) return getCurrent();
118
    return null;
119
    }
120

  
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

  
123
  public boolean matchesQuats(int[] quats)
124
    {
125
    int numQuats = quats.length;
126

  
127
    for(int q=0; q<numQuats; q++)
128
      {
129
      int[] eq = mEndQuats[q];
130
      if( eq!=null && doesntMatch(quats[q],eq) ) return false;
131
      }
132

  
133
    return true;
134
    }
135

  
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

  
138
  private boolean incIndices()
139
    {
140
    for(int i=mIndices.length-1; i>=0; i--)
141
      {
142
      int[] q = mEndQuats[i];
143
      int len = q!=null ? q.length-1 : 0;
144

  
145
      if( mIndices[i]<len )
146
        {
147
        mIndices[i]++;
148
        return true;
149
        }
150
      }
151

  
152
    return false;
153
    }
154

  
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156

  
157
  private boolean doesntMatch(int quat, int[] endquats)
158
    {
159
    for(int endquat : endquats)
160
      if( quat==endquat ) return false;
161

  
162
    return true;
163
    }
164

  
165
///////////////////////////////////////////////////////////////////////////////////////////////////
166

  
167
  private int[] getCurrent()
168
    {
169
    int len = mEndQuats.length;
170

  
171
    for(int q=0; q<len; q++)
172
      {
173
      int[] qs = mEndQuats[q];
174
      mTmp[q] = (qs==null ? -1 : qs[mIndices[q]]);
175
      }
176

  
177
    return mTmp;
178
    }
179
}

Also available in: Unified diff