Revision bdcb662f
Added by Leszek Koltunski about 1 year ago
src/main/java/org/distorted/objectlib/tablebases/TablebasesPruning.java | ||
---|---|---|
19 | 19 |
|
20 | 20 |
public abstract class TablebasesPruning extends TablebasesAbstract |
21 | 21 |
{ |
22 |
private final int mGodsNumber; |
|
23 |
|
|
22 | 24 |
private boolean mInitialized; |
23 | 25 |
private PruningTable[] mHighTables; |
24 | 26 |
private PruningTable[] mMidTables; |
25 |
private int mGodsNumber, mLowestHigh, mHighestMid, mLowestMid;
|
|
27 |
private int mLowestHigh, mHighestMid, mLowestMid; |
|
26 | 28 |
|
27 | 29 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
28 | 30 |
|
29 | 31 |
abstract int[] getMidPruningLevels(); |
30 | 32 |
abstract int[] getHighPruningLevels(); |
31 | 33 |
abstract int getGodsNumber(); |
34 |
abstract boolean moveCanProceed(int lastA, int lastL, int currA, int currL); |
|
32 | 35 |
|
33 | 36 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
34 | 37 |
|
... | ... | |
83 | 86 |
|
84 | 87 |
for(int i=0; i<mid ; i++) mMidTables[i] = createPruningTable(res,midIDs[i] ); |
85 | 88 |
for(int i=0; i<high; i++) mHighTables[i]= createPruningTable(res,highIDs[i]); |
89 |
|
|
90 |
computeLowHigh(); |
|
86 | 91 |
} |
87 | 92 |
|
88 | 93 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
118 | 123 |
for(int i=0; i<numHighLevels; i++) |
119 | 124 |
mHighTables[i] = new PruningTable(mTablebase,highLevels[i]); |
120 | 125 |
|
126 |
computeLowHigh(); |
|
127 |
|
|
121 | 128 |
mInitialized = true; |
122 | 129 |
} |
123 | 130 |
|
... | ... | |
133 | 140 |
|
134 | 141 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
135 | 142 |
|
136 |
public int[][] solution(int index, int[] extra) |
|
143 |
private void computeLowHigh() |
|
144 |
{ |
|
145 |
mLowestHigh = mGodsNumber+1; |
|
146 |
int numHigh = mHighTables==null ? 0 : mHighTables.length; |
|
147 |
|
|
148 |
for( int i=0; i<numHigh; i++ ) |
|
149 |
{ |
|
150 |
int level = mHighTables[i].getLevel(); |
|
151 |
if( i==0 || level<mLowestHigh ) mLowestHigh=level; |
|
152 |
} |
|
153 |
|
|
154 |
mLowestMid = 0; |
|
155 |
mHighestMid= 0; |
|
156 |
int numMid = mMidTables==null ? 0 : mMidTables.length; |
|
157 |
|
|
158 |
for( int i=0; i<numMid; i++ ) |
|
159 |
{ |
|
160 |
int level = mMidTables[i].getLevel(); |
|
161 |
if( i==0 || level<mLowestMid ) mLowestMid =level; |
|
162 |
if( i==0 || level>mHighestMid ) mHighestMid=level; |
|
163 |
} |
|
164 |
} |
|
165 |
|
|
166 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
167 |
|
|
168 |
public int traverseDownTable(int index, PruningTable[] tables, int tableIndex, int lastA, int lastR, int[] move, int[] tmpQuats) |
|
169 |
{ |
|
170 |
int[] quats = getQuats(index); |
|
171 |
int numQuats = quats.length; |
|
172 |
|
|
173 |
move[0]=0; |
|
174 |
move[1]=0; |
|
175 |
move[2]=1; |
|
176 |
move[3]=1; |
|
177 |
|
|
178 |
for(int ax=0; ax<mNumAxis; ax++) |
|
179 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
180 |
mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax); |
|
181 |
|
|
182 |
for(int s=0; s<mScalingFactor; s++) |
|
183 |
{ |
|
184 |
int ax = move[0]; |
|
185 |
int layer = move[1]; |
|
186 |
int quat = move[3]; |
|
187 |
|
|
188 |
if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,move[0],move[1]) ) |
|
189 |
{ |
|
190 |
int bitLayer = (1<<layer); |
|
191 |
System.arraycopy(quats, 0, tmpQuats, 0, numQuats); |
|
192 |
|
|
193 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
194 |
if( mRotRow[cubit][ax]==bitLayer ) |
|
195 |
{ |
|
196 |
int currQuat = tmpQuats[cubit]; |
|
197 |
int newQuat = getMultQuat(quat,currQuat); |
|
198 |
tmpQuats[cubit] = newQuat; |
|
199 |
} |
|
200 |
|
|
201 |
int childIndex = getIndex(tmpQuats); |
|
202 |
|
|
203 |
if( tableIndex>0 ) |
|
204 |
{ |
|
205 |
if( tables[tableIndex-1].contains(childIndex) ) return childIndex; |
|
206 |
} |
|
207 |
else if( !tables[0].contains(childIndex) ) |
|
208 |
{ |
|
209 |
if( tables.length<=1 || !tables[1].contains(childIndex) ) return childIndex; |
|
210 |
} |
|
211 |
} |
|
212 |
|
|
213 |
getNextAxisLayerAngleQuat(move); |
|
214 |
} |
|
215 |
|
|
216 |
return -1; |
|
217 |
} |
|
218 |
|
|
219 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
220 |
|
|
221 |
private int traversePruningBlock(int[][] moves, PruningTable[] tables, int tableIndex, int index, int lastA, int lastR) |
|
137 | 222 |
{ |
223 |
int movesIndex = 1; |
|
224 |
int[] move = moves[movesIndex]; |
|
225 |
int[] tmpQuats = new int[4]; |
|
226 |
|
|
227 |
do |
|
228 |
{ |
|
229 |
index = traverseDownTable(index,tables,tableIndex,lastA,lastR,move,tmpQuats); |
|
230 |
lastA = move[0]; |
|
231 |
lastR = move[1]; |
|
232 |
tableIndex--; |
|
233 |
movesIndex++; |
|
234 |
move = moves[movesIndex]; |
|
235 |
} |
|
236 |
while( tableIndex>=0 ); |
|
237 |
|
|
238 |
return index; |
|
239 |
} |
|
240 |
|
|
241 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
242 |
// ret: [0][] --> (new index,new depth,?,?) ; [1...N-1][] --> moves. (or null if index not in High) |
|
243 |
|
|
244 |
private int[][] traverseBlock(int index, PruningTable[] tables, int lastA, int lastR) |
|
245 |
{ |
|
246 |
int num = (tables==null) ? 0 : tables.length; |
|
247 |
int tableIndex = -1; |
|
248 |
|
|
249 |
for( int i=0; i<num; i++ ) |
|
250 |
if( tables[i].contains(index) ) |
|
251 |
{ |
|
252 |
tableIndex = i; |
|
253 |
break; |
|
254 |
} |
|
255 |
|
|
256 |
if( tableIndex<0 ) return null; |
|
257 |
|
|
258 |
int[][] ret = new int[tableIndex+2][4]; |
|
259 |
ret[0][1] = tables[0].getLevel()-1; |
|
260 |
ret[0][0] = traversePruningBlock(ret,tables,tableIndex,index,lastA, lastR); |
|
261 |
|
|
262 |
return ret; |
|
263 |
} |
|
264 |
|
|
265 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
266 |
|
|
267 |
private int midTablesContain(int index) |
|
268 |
{ |
|
269 |
int num = mMidTables.length; |
|
270 |
|
|
271 |
for( int i=0; i<num; i++ ) |
|
272 |
if( mMidTables[i].contains(index) ) |
|
273 |
return i; |
|
274 |
|
|
275 |
return -1; |
|
276 |
} |
|
277 |
|
|
278 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
279 |
|
|
280 |
private boolean jumpMidZeroRecursive(int index, int jump, int depth, int lastA, int lastR, int[][] solution) |
|
281 |
{ |
|
282 |
int[] quats = getQuats(index); |
|
283 |
int numQuats = quats.length; |
|
284 |
int[] move = solution[depth]; |
|
285 |
int[] tmp = new int[mNumCubits]; |
|
286 |
|
|
287 |
move[0]=0; |
|
288 |
move[1]=0; |
|
289 |
move[2]=1; |
|
290 |
move[3]=1; |
|
291 |
|
|
292 |
for(int ax=0; ax<mNumAxis; ax++) |
|
293 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
294 |
mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax); |
|
295 |
|
|
296 |
for(int s=0; s<mScalingFactor; s++) |
|
297 |
{ |
|
298 |
int ax = move[0]; |
|
299 |
int layer = move[1]; |
|
300 |
int quat = move[3]; |
|
301 |
|
|
302 |
if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,ax,layer) ) |
|
303 |
{ |
|
304 |
int bitLayer = (1<<layer); |
|
305 |
System.arraycopy(quats, 0, tmp, 0, numQuats); |
|
306 |
|
|
307 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
308 |
if( mRotRow[cubit][ax]==bitLayer ) |
|
309 |
{ |
|
310 |
int currQuat = tmp[cubit]; |
|
311 |
int newQuat = getMultQuat(quat,currQuat); |
|
312 |
tmp[cubit] = newQuat; |
|
313 |
} |
|
314 |
|
|
315 |
int childIndex = getIndex(tmp); |
|
316 |
|
|
317 |
if( childIndex==0 ) |
|
318 |
{ |
|
319 |
solution[0][0] = childIndex; |
|
320 |
solution[0][1] = 0; |
|
321 |
return true; |
|
322 |
} |
|
323 |
|
|
324 |
int containingTable = midTablesContain(childIndex); |
|
325 |
|
|
326 |
if( containingTable>=0 ) |
|
327 |
{ |
|
328 |
solution[0][0] = childIndex; |
|
329 |
solution[0][1] = mMidTables[containingTable].getLevel(); |
|
330 |
return true; |
|
331 |
} |
|
332 |
|
|
333 |
if( jump>1 && jumpMidZeroRecursive(childIndex, jump-1, depth+1, ax, layer, solution) ) |
|
334 |
{ |
|
335 |
return true; |
|
336 |
} |
|
337 |
} |
|
338 |
|
|
339 |
getNextAxisLayerAngleQuat(move); |
|
340 |
} |
|
341 |
|
|
342 |
return false; |
|
343 |
} |
|
344 |
|
|
345 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
346 |
// ret: [0][] --> (?,old depth,?,?) ; [1...N-1][] --> moves. |
|
347 |
|
|
348 |
private int[][] jumpToMidOrZero(int index, int maxJump, int lastA, int lastR) |
|
349 |
{ |
|
350 |
int[][] solution = new int[maxJump+1][4]; |
|
351 |
|
|
352 |
for(int i=1; i<maxJump; i++) |
|
353 |
if( jumpMidZeroRecursive(index,i,1,lastA,lastR,solution) ) |
|
354 |
return solution; |
|
355 |
|
|
356 |
return null; |
|
357 |
} |
|
358 |
|
|
359 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
360 |
|
|
361 |
private boolean jumpZeroRecursive(int index, int jump, int depth, int lastA, int lastR, int[][] solution) |
|
362 |
{ |
|
363 |
int[] quats = getQuats(index); |
|
364 |
int numQuats = quats.length; |
|
365 |
int[] move = solution[depth]; |
|
366 |
int[] tmp = new int[mNumCubits]; |
|
367 |
|
|
368 |
android.util.Log.e("D", "trying 0rec: index="+index); |
|
369 |
|
|
370 |
move[0]=0; |
|
371 |
move[1]=0; |
|
372 |
move[2]=1; |
|
373 |
move[3]=1; |
|
374 |
|
|
375 |
for(int ax=0; ax<mNumAxis; ax++) |
|
376 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
377 |
mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax); |
|
378 |
|
|
379 |
for(int s=0; s<mScalingFactor; s++) |
|
380 |
{ |
|
381 |
int ax = move[0]; |
|
382 |
int layer = move[1]; |
|
383 |
int quat = move[3]; |
|
384 |
|
|
385 |
if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,move[0],move[1]) ) |
|
386 |
{ |
|
387 |
int bitLayer = (1<<layer); |
|
388 |
System.arraycopy(quats, 0, tmp, 0, numQuats); |
|
389 |
|
|
390 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
391 |
if( mRotRow[cubit][ax]==bitLayer ) |
|
392 |
{ |
|
393 |
int currQuat = tmp[cubit]; |
|
394 |
int newQuat = getMultQuat(quat,currQuat); |
|
395 |
tmp[cubit] = newQuat; |
|
396 |
} |
|
397 |
|
|
398 |
int childIndex = getIndex(tmp); |
|
399 |
if( childIndex==0 ) |
|
400 |
{ |
|
401 |
android.util.Log.e("D", "END: ax="+ax+" layer="+layer+" angle: "+move[2]); |
|
402 |
return true; |
|
403 |
} |
|
404 |
if( jump>1 && jumpZeroRecursive(childIndex, jump-1, depth+1, ax, layer, solution) ) |
|
405 |
{ |
|
406 |
android.util.Log.e("D", "REC: ax="+ax+" layer="+layer+" angle: "+move[2]); |
|
407 |
return true; |
|
408 |
} |
|
409 |
} |
|
410 |
|
|
411 |
getNextAxisLayerAngleQuat(move); |
|
412 |
} |
|
413 |
|
|
414 |
return false; |
|
415 |
} |
|
416 |
|
|
417 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
418 |
// ret: [0][] --> (?,old depth,?,?) ; [1...N-1][] --> moves. |
|
419 |
|
|
420 |
private int[][] jumpToZero(int index, int maxJump, int lastA, int lastR) |
|
421 |
{ |
|
422 |
int[][] solution = new int[maxJump+1][4]; |
|
423 |
|
|
424 |
for(int i=1; i<maxJump; i++) |
|
425 |
if( jumpZeroRecursive(index,i,1,lastA,lastR,solution) ) |
|
426 |
return solution; |
|
427 |
|
|
138 | 428 |
return null; |
139 | 429 |
} |
430 |
|
|
431 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
432 |
|
|
433 |
private int[][] concatenateMoves(int[][] high, int[][] jump1, int[][] mid, int[][] jump2) |
|
434 |
{ |
|
435 |
int len1 = high ==null ? 0 : high.length-1; |
|
436 |
int len2 = jump1==null ? 0 : jump1[0][1]; |
|
437 |
int len3 = mid ==null ? 0 : mid.length-1; |
|
438 |
int len4 = jump2==null ? 0 : jump2[0][1]; |
|
439 |
|
|
440 |
int[][] moves = new int[len1+len2+len3+len4][]; |
|
441 |
int index = 0; |
|
442 |
|
|
443 |
for(int i=0; i<len1; i++) moves[index++] = high[i+1]; |
|
444 |
for(int i=0; i<len2; i++) moves[index++] = jump1[i+1]; |
|
445 |
for(int i=0; i<len3; i++) moves[index++] = mid[i+1]; |
|
446 |
for(int i=0; i<len4; i++) moves[index++] = jump2[i+1]; |
|
447 |
|
|
448 |
convertMoves(moves); |
|
449 |
|
|
450 |
return moves; |
|
451 |
} |
|
452 |
|
|
453 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
454 |
|
|
455 |
public int[][] solution(int index, int[] extra) |
|
456 |
{ |
|
457 |
if( index==0 ) return null; |
|
458 |
int lastA=-1, lastR=0; |
|
459 |
int[][] highMoves = traverseBlock(index,mHighTables,lastA,lastR); |
|
460 |
|
|
461 |
if( highMoves!=null ) |
|
462 |
{ |
|
463 |
index = highMoves[0][0]; |
|
464 |
int len = highMoves.length; |
|
465 |
lastA = highMoves[len-1][0]; |
|
466 |
lastR = highMoves[len-1][1]; |
|
467 |
} |
|
468 |
|
|
469 |
int maxJump = Math.max(mLowestHigh-1-mHighestMid,mLowestMid/2); |
|
470 |
int[][] jump1Moves = jumpToMidOrZero(index,maxJump,lastA,lastR); |
|
471 |
|
|
472 |
if( jump1Moves!=null ) |
|
473 |
{ |
|
474 |
if( jump1Moves[0][0]==0 ) |
|
475 |
{ |
|
476 |
return concatenateMoves(null,null,null,jump1Moves); |
|
477 |
} |
|
478 |
if( jump1Moves[0][1]==mLowestMid ) |
|
479 |
{ |
|
480 |
int[][] jump2Moves = jumpToZero(index,mLowestMid-1,-1,0); |
|
481 |
if( jump2Moves==null ) throw new RuntimeException("1 error jumping to 0"); |
|
482 |
return concatenateMoves(null,null,null,jump2Moves); |
|
483 |
} |
|
484 |
|
|
485 |
index = jump1Moves[0][0]; |
|
486 |
int len = jump1Moves.length; |
|
487 |
lastA = jump1Moves[len-1][0]; |
|
488 |
lastR = jump1Moves[len-1][1]; |
|
489 |
} |
|
490 |
|
|
491 |
int[][] midMoves = traverseBlock(index,mMidTables,lastA,lastR); |
|
492 |
if( midMoves!=null ) |
|
493 |
{ |
|
494 |
index = midMoves[0][0]; |
|
495 |
int len = midMoves.length; |
|
496 |
lastA = midMoves[len-1][0]; |
|
497 |
lastR = midMoves[len-1][1]; |
|
498 |
} |
|
499 |
else throw new RuntimeException("error traversing mid Tables"); |
|
500 |
|
|
501 |
int[][] jump2Moves = jumpToZero(index,mLowestMid-1,lastA,lastR); |
|
502 |
if( jump2Moves==null ) throw new RuntimeException("2 error jumping to 0"); |
|
503 |
return concatenateMoves(highMoves,jump1Moves,midMoves,jump2Moves); |
|
504 |
} |
|
140 | 505 |
} |
Also available in: Unified diff
Progress with TablebasesPruning