introduce bitloops

This commit is contained in:
mike
2026-01-20 04:51:32 +01:00
parent 0dcfbebcb0
commit ba90818b66
4 changed files with 29 additions and 23 deletions

View File

@@ -34,7 +34,7 @@ public class Main {
@NoArgsConstructor
public static class Opts {
static int SSIZE = 20;
static int SSIZE = 23;
public int seed = (int) (System.nanoTime() ^ System.currentTimeMillis());
public int clueSize = SSIZE;
public int pop = SSIZE * 2;

View File

@@ -20,7 +20,8 @@ public final class Masker {
private final long[] activeSHi = new long[SwedishGenerator.SIZE];
private final long[] adjLo = new long[SwedishGenerator.SIZE];
private final long[] adjHi = new long[SwedishGenerator.SIZE];
private final int[] rCount = new int[8];
private final int[] cCount = new int[9];
public Masker(Rng rng, int[] stack, Clues cache) {
this.rng = rng;
this.stack = stack;
@@ -194,7 +195,10 @@ public final class Masker {
long lo_cl = grid.lo, hi_cl = grid.hi;
long penalty = (((long) Math.abs(grid.clueCount() - clueSize)) * 16000L);
boolean hasSlots = false;
if (!isValid(grid, 2)) return 1_000_000_000L;
/* if (!isValid(grid, 2)) {
throw new RuntimeException("Invalid grid configuration for mask fitness calculation");
//return 1_000_000_000L;
}*/
int numClues = 0;
for (long bits = lo_cl; bits != X; bits &= bits - 1) {
@@ -288,8 +292,8 @@ public final class Masker {
if (!hasSlots) return 1_000_000_000L;
int[] rCount = new int[8];
int[] cCount = new int[9];
Arrays.fill(rCount, 0);
Arrays.fill(cCount, 0);
for (int i = 0; i < numClues; i++) {
int idx = activeCIdx[i];
rCount[idx & 7]++;
@@ -383,13 +387,12 @@ public final class Masker {
else penalty += 1000;
}
long nclLo = ~lo_cl & MASK_LO;
long nclHi = ~hi_cl & MASK_HI;
long hNbrLo = (nclLo >> 8) | (nclLo << 8) | (nclHi << 56);
long hNbrHi = (nclHi >> 8) | (nclLo >> 56);
long vNbrLo = ((nclLo & ~0x0101010101010101L) >> 1) | ((nclLo & ~0x8080808080808080L) << 1);
long vNbrHi = ((nclHi & ~0x01L) >> 1) | ((nclHi & ~0x80L) << 1);
//long nclLo = ~lo_cl & MASK_LO;
//long nclHi = ~hi_cl & MASK_HI;
//long hNbrLo = (nclLo >> 8) | (nclLo << 8) | (nclHi << 56);
//long hNbrHi = (nclHi >> 8) | (nclLo >> 56);
//long vNbrLo = ((nclLo & ~0x0101010101010101L) >> 1) | ((nclLo & ~0x8080808080808080L) << 1);
//long vNbrHi = ((nclHi & ~0x01L) >> 1) | ((nclHi & ~0x80L) << 1);
//penalty += bitCount(nclLo & ~cHLo & hNbrLo) * 800;
//penalty += bitCount(nclLo & ~cVLo & vNbrLo) * 800;
//penalty += bitCount(nclHi & ~cHHi & hNbrHi) * 800;

View File

@@ -40,7 +40,7 @@ public record SwedishGenerator() {
public static final int MAX_WORD_LENGTH = Config.PUZZLE_ROWS;
public static final int MAX_WORD_LENGTH_PLUS_ONE = MAX_WORD_LENGTH + 1;
public static final int MIN_LEN = 2;//Neighbors9x8.MIN_LEN;//Config.MIN_LEN;
public static final int MAX_TRIES_PER_SLOT = 700;//Config.MAX_TRIES_PER_SLOT;
public static final int MAX_TRIES_PER_SLOT = 400;//Config.MAX_TRIES_PER_SLOT;
public static final int STACK_SIZE = 128;
public static final long RANGE_0_SIZE = Neighbors9x8.RANGE_0_SIZE;// (long) SIZE_MIN_1 - 0L + 1L
public static final long RANGE_0_624 = Neighbors9x8.RANGE_0_624;//624L - 0L + 1L;

View File

@@ -5,6 +5,7 @@ import lombok.val;
import org.junit.jupiter.api.Test;
import puzzle.Export.Clued;
import puzzle.Export.Gridded;
import puzzle.Masker.Clues;
import puzzle.SwedishGenerator.DictEntry;
import puzzle.SwedishGenerator.Rng;
import puzzle.SwedishGenerator.Slotinfo;
@@ -15,6 +16,9 @@ import static puzzle.SwedishGenerator.fillMask;
public class PerformanceTest {
final DictEntry[] EN = DictData.DICT.index();
void main() {
testPerformance();
}
@Test
void testPerformance() {
val rng = new Rng(42);
@@ -22,11 +26,13 @@ public class PerformanceTest {
// 1. Stress test Clue Generation (Mask Generation)
System.out.println("[DEBUG_LOG] --- Mask Generation Performance ---");
int[] clueSizes = { 20, 25, 30 };
var arr = new Clues[3];
int c = 0;
for (int size : clueSizes) {
long t0 = System.currentTimeMillis();
val masker = new Masker(rng, new int[SwedishGenerator.STACK_SIZE], Masker.Clues.createEmpty());
// Increased population and generations for stress
val mask = masker.generateMask(size, 200, 100, 50);
arr[c++] = masker.generateMask(size, 200, 100, 50);
long t1 = System.currentTimeMillis();
double duration = (t1 - t0) / 1000.0;
System.out.printf(Locale.ROOT, "[DEBUG_LOG] Size %d (pop=200, gen=100): %.3fs%n", size, duration);
@@ -36,24 +42,24 @@ public class PerformanceTest {
// 2. Stress test Word Filler
System.out.println("[DEBUG_LOG] \n--- Word Filler Performance ---");
c = 0;
for (int size : clueSizes) {
val masker = new Masker(rng, new int[SwedishGenerator.STACK_SIZE], Masker.Clues.createEmpty());
val mask = masker.generateMask(size, 100, 50, 20);
val slotInfo = Masker.slots(mask, EN);
long t0 = System.currentTimeMillis();
// Try to fill multiple times to get a better average
int iterations = 1;
int iterations = 10;
long totalNodes = 0;
long totalBacktracks = 0;
int successCount = 0;
for (int i = 0; i < iterations; i++) {
val result = fillMask(rng, slotInfo, Slotinfo.grid(slotInfo));
val slotInfo = Masker.slots(arr[c], EN);
val result = fillMask(rng, slotInfo, Slotinfo.grid(slotInfo));
if (result.ok()) successCount++;
totalNodes += result.nodes();
totalBacktracks += result.backtracks();
}
c++;
long t1 = System.currentTimeMillis();
double totalDuration = (t1 - t0) / 1000.0;
@@ -61,9 +67,6 @@ public class PerformanceTest {
size, successCount, iterations, totalNodes / iterations, totalBacktracks / iterations, totalDuration);
}
}
void main() {
testIncrementalComplexity();
}
@Test
void testIncrementalComplexity() {