Revision a6956092
Added by Leszek Koltunski 10 months ago
src/main/java/org/distorted/objectlib/algsolvers/MitmTable.java | ||
---|---|---|
13 | 13 |
|
14 | 14 |
class MitmTable |
15 | 15 |
{ |
16 |
private final int mBytesPerEntry; |
|
17 | 16 |
private final int mBitsPerQuat; |
18 | 17 |
private final int mNumCubits; |
18 |
private final boolean[] mUseCubit; |
|
19 | 19 |
private final MitmTableDataStructure mData; |
20 | 20 |
|
21 |
private int mBytesPerEntry; |
|
22 |
|
|
21 | 23 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
22 | 24 |
|
23 | 25 |
MitmTable(int numCubits, int numQuats) |
... | ... | |
25 | 27 |
mNumCubits = numCubits; |
26 | 28 |
double tmp = Math.log(numQuats) / Math.log(2); |
27 | 29 |
mBitsPerQuat = (int)Math.ceil(tmp); |
28 |
double numBytes = numCubits*mBitsPerQuat/8.0; |
|
29 |
mBytesPerEntry = (int)Math.ceil(numBytes); // this many bytes will be needed to store one position |
|
30 |
mUseCubit = new boolean[mNumCubits]; |
|
30 | 31 |
|
31 | 32 |
mData = new MitmTableDataStructure(); |
32 | 33 |
} |
... | ... | |
62 | 63 |
|
63 | 64 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
64 | 65 |
|
65 |
private String getQuatString(int[] quats)
|
|
66 |
static String getQuatString(int[] quats)
|
|
66 | 67 |
{ |
67 | 68 |
StringBuilder sb = new StringBuilder(); |
68 | 69 |
|
... | ... | |
75 | 76 |
return sb.toString(); |
76 | 77 |
} |
77 | 78 |
|
79 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
80 |
|
|
81 |
static String getMultiQuatString(int[][] quats) |
|
82 |
{ |
|
83 |
StringBuilder sb = new StringBuilder(); |
|
84 |
|
|
85 |
for( int[] quat : quats) |
|
86 |
{ |
|
87 |
sb.append('['); |
|
88 |
int len = quat==null ? 0 : quat.length; |
|
89 |
|
|
90 |
for( int q=0; q<len; q++ ) |
|
91 |
{ |
|
92 |
sb.append(quat[q]); |
|
93 |
if(q<len-1) sb.append(','); |
|
94 |
} |
|
95 |
sb.append(']'); |
|
96 |
sb.append(' '); |
|
97 |
} |
|
98 |
|
|
99 |
return sb.toString(); |
|
100 |
} |
|
78 | 101 |
|
79 | 102 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
80 | 103 |
|
81 |
private String getSigString(byte[] sig)
|
|
104 |
static String getSigString(byte[] sig)
|
|
82 | 105 |
{ |
83 | 106 |
StringBuilder sb = new StringBuilder(); |
84 | 107 |
|
... | ... | |
98 | 121 |
return mBytesPerEntry; |
99 | 122 |
} |
100 | 123 |
|
124 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
125 |
|
|
126 |
void setupSize(int[][] endQuats) |
|
127 |
{ |
|
128 |
int numUsedCubits = 0; |
|
129 |
|
|
130 |
for(int e=0; e<mNumCubits; e++) |
|
131 |
{ |
|
132 |
if( endQuats[e]!=null ) |
|
133 |
{ |
|
134 |
numUsedCubits++; |
|
135 |
mUseCubit[e] = true; |
|
136 |
} |
|
137 |
else |
|
138 |
{ |
|
139 |
mUseCubit[e] = false; |
|
140 |
} |
|
141 |
} |
|
142 |
|
|
143 |
double numBytes = numUsedCubits*mBitsPerQuat/8.0; |
|
144 |
mBytesPerEntry = (int)Math.ceil(numBytes); // this many bytes will be needed to store one position |
|
145 |
} |
|
146 |
|
|
101 | 147 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
102 | 148 |
|
103 | 149 |
void build(SolvedObject object, int len) |
... | ... | |
123 | 169 |
boolean thereIsNext; |
124 | 170 |
int branching = object.getBranchingFactor(); |
125 | 171 |
int[] backward = new int[lenb]; |
172 |
int[] quats = object.getCubitQuats(); |
|
173 |
int[] rem = new int[mNumCubits]; |
|
174 |
for(int c=0; c<mNumCubits; c++) rem[c] = quats[c]; |
|
126 | 175 |
|
127 | 176 |
do |
128 | 177 |
{ |
... | ... | |
131 | 180 |
|
132 | 181 |
if( reached!=null ) |
133 | 182 |
{ |
183 |
object.setUpStartingQuats(rem); |
|
134 | 184 |
int[] forward = new int[lenf]; |
135 | 185 |
int numMoves = reachForward(object,reached,forward,lenf); |
136 |
return joinSequences(forward,numMoves,backward); |
|
186 |
return joinSequences(object,forward,numMoves,backward);
|
|
137 | 187 |
} |
138 | 188 |
|
139 | 189 |
thereIsNext = getNext(endQuats,indices); |
140 | 190 |
} |
141 | 191 |
while( thereIsNext ); |
142 | 192 |
|
193 |
object.setUpStartingQuats(rem); |
|
143 | 194 |
return null; |
144 | 195 |
} |
145 | 196 |
|
... | ... | |
190 | 241 |
ret[0] = m; |
191 | 242 |
int numMoves = reachForwardRecursive(object,quats,ret,1,len-1); |
192 | 243 |
object.backMove(m); |
193 |
|
|
194 | 244 |
if( numMoves>=0 ) return numMoves+1; |
195 | 245 |
} |
196 | 246 |
} |
... | ... | |
237 | 287 |
if( l1==l2 ) |
238 | 288 |
{ |
239 | 289 |
for(int i=0; i<l1; i++) |
240 |
if( q1[i]!=q2[i] ) return false; |
|
290 |
{ |
|
291 |
int a1 = q1[i]; |
|
292 |
int a2 = q2[i]; |
|
293 |
|
|
294 |
if( a1!=a2 && a1>=0 && a2>=0 ) return false; |
|
295 |
} |
|
241 | 296 |
|
242 | 297 |
return true; |
243 | 298 |
} |
... | ... | |
247 | 302 |
|
248 | 303 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
249 | 304 |
|
250 |
private int[] joinSequences(int[] forward, int lenf, int[] backward) |
|
305 |
private int[] joinSequences(SolvedObject object, int[] forward, int lenf, int[] backward)
|
|
251 | 306 |
{ |
252 | 307 |
int lenb = backward.length; |
253 | 308 |
|
... | ... | |
255 | 310 |
ret[0] = lenf+lenb; |
256 | 311 |
|
257 | 312 |
for(int i=0; i<lenf; i++) ret[1+i ] = forward[i]; |
258 |
for(int i=0; i<lenb; i++) ret[1+i+lenf] = backward[i];
|
|
313 |
for(int i=0; i<lenb; i++) ret[1+i+lenf] = object.invertMove(backward[i]);
|
|
259 | 314 |
|
260 | 315 |
return ret; |
261 | 316 |
} |
... | ... | |
317 | 372 |
{ |
318 | 373 |
byte[] ret = new byte[mBytesPerEntry]; |
319 | 374 |
|
320 |
for(int q=0; q<mNumCubits; q++) |
|
321 |
{ |
|
322 |
int index = q*mBitsPerQuat/8; |
|
323 |
int offset= q*mBitsPerQuat-index*8; |
|
324 |
int quat = quats[q]; |
|
325 |
int remaining = mBitsPerQuat; |
|
326 |
|
|
327 |
while(remaining>0) |
|
375 |
for(int c=0, i=0; c<mNumCubits; c++) |
|
376 |
if( mUseCubit[c] ) |
|
328 | 377 |
{ |
329 |
int toBeWritten = remaining+offset>8 ? 8-offset : remaining; |
|
330 |
writePackedByte(ret,index,offset,toBeWritten,remaining,quat); |
|
331 |
remaining -= toBeWritten; |
|
332 |
offset = 0; |
|
333 |
index++; |
|
334 |
int mask = (1<<remaining)-1; |
|
335 |
quat &= mask; |
|
378 |
int index = i*mBitsPerQuat/8; |
|
379 |
int offset= i*mBitsPerQuat-index*8; |
|
380 |
i++; |
|
381 |
|
|
382 |
int quat = quats[c]; |
|
383 |
int remaining = mBitsPerQuat; |
|
384 |
|
|
385 |
while(remaining>0) |
|
386 |
{ |
|
387 |
int toBeWritten = remaining+offset>8 ? 8-offset : remaining; |
|
388 |
writePackedByte(ret,index,offset,toBeWritten,remaining,quat); |
|
389 |
remaining -= toBeWritten; |
|
390 |
offset = 0; |
|
391 |
index++; |
|
392 |
int mask = (1<<remaining)-1; |
|
393 |
quat &= mask; |
|
394 |
} |
|
336 | 395 |
} |
337 |
} |
|
338 | 396 |
|
339 | 397 |
return ret; |
340 | 398 |
} |
... | ... | |
358 | 416 |
{ |
359 | 417 |
int[] ret = new int[mNumCubits]; |
360 | 418 |
|
361 |
for(int q=0; q<mNumCubits; q++)
|
|
419 |
for(int c=0,i=0; c<mNumCubits; c++)
|
|
362 | 420 |
{ |
363 |
int index = q*mBitsPerQuat/8;
|
|
364 |
int offset= q*mBitsPerQuat-index*8;
|
|
421 |
int index = i*mBitsPerQuat/8;
|
|
422 |
int offset= i*mBitsPerQuat-index*8;
|
|
365 | 423 |
int remaining = mBitsPerQuat; |
366 | 424 |
|
367 |
while(remaining>0) |
|
425 |
if( mUseCubit[c] ) |
|
426 |
{ |
|
427 |
while(remaining>0) |
|
428 |
{ |
|
429 |
byte sig = signature[index]; |
|
430 |
int toBeRead = remaining+offset>8 ? 8-offset : remaining; |
|
431 |
readPackedByte(ret,c,toBeRead,sig,offset); |
|
432 |
remaining -= toBeRead; |
|
433 |
offset = 0; |
|
434 |
index++; |
|
435 |
} |
|
436 |
|
|
437 |
i++; |
|
438 |
} |
|
439 |
else |
|
368 | 440 |
{ |
369 |
byte sig = signature[index]; |
|
370 |
int toBeRead = remaining+offset>8 ? 8-offset : remaining; |
|
371 |
readPackedByte(ret,q,toBeRead,sig,offset); |
|
372 |
remaining -= toBeRead; |
|
373 |
offset = 0; |
|
374 |
index++; |
|
441 |
ret[c] = -1; |
|
375 | 442 |
} |
376 | 443 |
} |
377 | 444 |
|
src/main/java/org/distorted/objectlib/algsolvers/MitmTableDataStructure.java | ||
---|---|---|
50 | 50 |
|
51 | 51 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
52 | 52 |
|
53 |
boolean add(byte[] bytes)
|
|
53 |
void add(byte[] bytes)
|
|
54 | 54 |
{ |
55 |
return mData.add(new ByteArray(bytes));
|
|
55 |
mData.add(new ByteArray(bytes)); |
|
56 | 56 |
} |
57 | 57 |
} |
src/main/java/org/distorted/objectlib/algsolvers/PhaseSolutionFinder.java | ||
---|---|---|
45 | 45 |
|
46 | 46 |
void prepareForSolution(int[] startingQuats) |
47 | 47 |
{ |
48 |
mForwardDepth = computeForwardDepth(); |
|
49 | 48 |
mObject.setUpStartingQuats(startingQuats); |
50 | 49 |
} |
51 | 50 |
|
... | ... | |
53 | 52 |
|
54 | 53 |
void prepareForPhase(int[][] endQuats) |
55 | 54 |
{ |
55 |
mForwardDepth = computeForwardDepth(endQuats); |
|
56 | 56 |
mBackwardDepth = computeBackwardDepth(endQuats); |
57 | 57 |
} |
58 | 58 |
|
59 | 59 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
60 | 60 |
|
61 |
private int computeForwardDepth() |
|
61 |
private int computeForwardDepth(int[][] endQuats)
|
|
62 | 62 |
{ |
63 |
mTable.setupSize(endQuats); |
|
63 | 64 |
int bytesPerEntry = mTable.getBytesPerEntry(); |
64 | 65 |
int branchingFactor = mObject.getBranchingFactor(); |
65 | 66 |
int numEntries = MAX_MEMORY/bytesPerEntry; |
src/main/java/org/distorted/objectlib/algsolvers/SolvedObject.java | ||
---|---|---|
28 | 28 |
private final int mNumQuats; |
29 | 29 |
private final int mBranchingFactor; |
30 | 30 |
private final int[][] mMoveTable; |
31 |
private final int[] mMoveInterts; |
|
31 | 32 |
|
32 | 33 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
33 | 34 |
|
... | ... | |
42 | 43 |
|
43 | 44 |
mBranchingFactor= computeBranchingFactor(); |
44 | 45 |
mMoveTable = computeMoveTable(); |
45 |
int[] quatF = computeQuatForward(); |
|
46 |
int[] quatB = computeQuatBackward(); |
|
46 |
mMoveInterts = computeMoveInverts(); |
|
47 | 47 |
|
48 | 48 |
mQuatMult = new int[mNumQuats][mNumQuats]; |
49 | 49 |
|
50 | 50 |
for(int i=0; i<mNumQuats; i++) |
51 | 51 |
for(int j=0; j<mNumQuats; j++) mQuatMult[i][j] = mulQuat(i,j); |
52 | 52 |
|
53 |
int[] quatF = computeQuatForward(); |
|
54 |
int[] quatB = computeQuatBackward(); |
|
55 |
|
|
53 | 56 |
mCubits = new SolvedObjectCubit(mOrigPos,mAxis,cuts,mQuats,mQuatMult,mMoveTable,quatF,quatB); |
54 | 57 |
} |
55 | 58 |
|
... | ... | |
130 | 133 |
return true; |
131 | 134 |
} |
132 | 135 |
|
136 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
137 |
|
|
138 |
int invertMove(int moveIndex) |
|
139 |
{ |
|
140 |
return mMoveInterts[moveIndex]; |
|
141 |
} |
|
142 |
|
|
133 | 143 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
134 | 144 |
// note the minus in front of the sin() - we rotate counterclockwise |
135 | 145 |
// when looking towards the direction where the axis increases in values. |
136 | 146 |
|
137 |
private int makeQuaternionIndex(Static3D axis, int angleInDegrees)
|
|
147 |
private int makeQuaternionIndex(int axisIndex, int angleInDegrees)
|
|
138 | 148 |
{ |
139 | 149 |
while( angleInDegrees<0 ) angleInDegrees += 360; |
140 | 150 |
angleInDegrees %= 360; |
... | ... | |
142 | 152 |
float cosA = (float)Math.cos(Math.PI*angleInDegrees/360); |
143 | 153 |
float sinA =-(float)Math.sqrt(1-cosA*cosA); |
144 | 154 |
|
155 |
Static3D axis = mAxis[axisIndex]; |
|
145 | 156 |
float axisX = axis.get0(); |
146 | 157 |
float axisY = axis.get1(); |
147 | 158 |
float axisZ = axis.get2(); |
... | ... | |
198 | 209 |
return ret; |
199 | 210 |
} |
200 | 211 |
|
212 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
213 |
|
|
214 |
private int[] computeMoveInverts() |
|
215 |
{ |
|
216 |
int[] ret = new int[mBranchingFactor]; |
|
217 |
|
|
218 |
for(int i=0; i<mBranchingFactor; i++) |
|
219 |
{ |
|
220 |
int[] move = mMoveTable[i]; |
|
221 |
int ax = move[0]; |
|
222 |
int row= move[1]; |
|
223 |
int ang= move[2]; |
|
224 |
int bas= mBasicAngles[ax][row]; |
|
225 |
|
|
226 |
for(int j=0; j<mBranchingFactor; j++) |
|
227 |
{ |
|
228 |
int[] move2 = mMoveTable[j]; |
|
229 |
int ax2 = move2[0]; |
|
230 |
int row2= move2[1]; |
|
231 |
int ang2= move2[2]; |
|
232 |
|
|
233 |
if( ax==ax2 && row==row2 && ang+ang2==bas ) |
|
234 |
{ |
|
235 |
ret[i] = j; |
|
236 |
break; |
|
237 |
} |
|
238 |
} |
|
239 |
} |
|
240 |
|
|
241 |
return ret; |
|
242 |
} |
|
243 |
|
|
201 | 244 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
202 | 245 |
|
203 | 246 |
private int[][] computeMoveTable() |
... | ... | |
231 | 274 |
{ |
232 | 275 |
int[] move = mMoveTable[i]; |
233 | 276 |
int axis = move[0]; |
277 |
int row = move[1]; |
|
234 | 278 |
int angle = move[2]; |
235 |
ret[i] = makeQuaternionIndex(mAxis[axis],angle); |
|
279 |
int basic = mBasicAngles[axis][row]; |
|
280 |
ret[i] = makeQuaternionIndex(axis,-angle*(360/basic)); |
|
236 | 281 |
} |
237 | 282 |
|
238 | 283 |
return ret; |
... | ... | |
248 | 293 |
{ |
249 | 294 |
int[] move = mMoveTable[i]; |
250 | 295 |
int axis = move[0]; |
251 |
int angle =-move[2]; |
|
252 |
ret[i] = makeQuaternionIndex(mAxis[axis],angle); |
|
296 |
int row = move[1]; |
|
297 |
int angle = move[2]; |
|
298 |
int basic = mBasicAngles[axis][row]; |
|
299 |
ret[i] = makeQuaternionIndex(axis,angle*(360/basic)); |
|
253 | 300 |
} |
254 | 301 |
|
255 | 302 |
return ret; |
src/main/java/org/distorted/objectlib/algsolvers/SolvedObjectCubit.java | ||
---|---|---|
78 | 78 |
for(int c=0; c<mNumCubits; c++) |
79 | 79 |
{ |
80 | 80 |
int q = mRotQuats[c]; |
81 |
int ji = mData[c].jumpIndices[q]; |
|
82 |
int bitmap = mData[ji].rotRowBitmaps[axisIndex]; |
|
83 |
if( (bitmap&rowBitmap) != 0 ) mRotQuats[c] = mQuatMult[quatIndex][q]; |
|
81 |
|
|
82 |
if( q>=0 ) |
|
83 |
{ |
|
84 |
int ji = mData[c].jumpIndices[q]; |
|
85 |
int bitmap = mData[ji].rotRowBitmaps[axisIndex]; |
|
86 |
if( (bitmap&rowBitmap) != 0 ) mRotQuats[c] = mQuatMult[quatIndex][q]; |
|
87 |
} |
|
84 | 88 |
} |
85 | 89 |
} |
86 | 90 |
|
... | ... | |
116 | 120 |
} |
117 | 121 |
|
118 | 122 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
123 |
// here we set the indices of cubits we don't care about at the moment to -1. |
|
119 | 124 |
|
120 | 125 |
void setUpQuats(int[][] quats, int[] indices) |
121 | 126 |
{ |
122 | 127 |
for(int c=0; c<mNumCubits; c++) |
123 | 128 |
{ |
124 | 129 |
int[] q = quats[c]; |
125 |
if( q!=null ) mRotQuats[c] = q[indices[c]];
|
|
130 |
mRotQuats[c] = q!=null ? q[indices[c]] : -1;
|
|
126 | 131 |
} |
127 | 132 |
} |
128 | 133 |
|
Also available in: Unified diff
Lots of bugfixes. Solving the white cross rotated by one move works now.