introduce bitloops

This commit is contained in:
mike
2026-01-17 01:30:50 +01:00
parent 4585c1f2eb
commit a2134f0dce
3 changed files with 27 additions and 22 deletions

View File

@@ -389,7 +389,9 @@ public class Main {
var mask = swe.generateMask(opts.clueSize, opts.pop, opts.gens, opts.offspring); var mask = swe.generateMask(opts.clueSize, opts.pop, opts.gens, opts.offspring);
if (mask == null) return null; if (mask == null) return null;
val multiThreaded = Thread.currentThread().getName().contains("pool"); val multiThreaded = Thread.currentThread().getName().contains("pool");
var filled = fillMask(rng, extractSlots(mask, dict.index()), mask.toGrid(), multiThreaded); var slots = extractSlots(mask, dict.index());
val slotInfo = scoreSlots(new int[slots.length], slots);
var filled = fillMask(rng, slotInfo, mask.toGrid(), multiThreaded);
TOTAL_NODES.addAndGet(filled.stats().nodes); TOTAL_NODES.addAndGet(filled.stats().nodes);
TOTAL_BACKTRACKS.addAndGet(filled.stats().backtracks); TOTAL_BACKTRACKS.addAndGet(filled.stats().backtracks);

View File

@@ -78,9 +78,9 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
@AllArgsConstructor @AllArgsConstructor
static class Pick { static class Pick {
Slot slot; Slotinfo slot;
int[] indices; int[] indices;
int count; int count;
} }
// 0b11 // 0b11
@@ -335,6 +335,10 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
} }
} }
static record Slotinfo(int key, long lo, long hi, int score, DictEntry entry) {
}
static record Slot(int key, long lo, long hi, DictEntry entry) { static record Slot(int key, long lo, long hi, DictEntry entry) {
static final int BIT_FOR_DIR = 2; static final int BIT_FOR_DIR = 2;
@@ -874,8 +878,9 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
return count; return count;
} }
static void scoreSlots(int[] slotScores, Slot[] slots) { static Slotinfo[] scoreSlots(int[] slotScores, Slot[] slots) {
val count = new byte[SIZE]; val count = new byte[SIZE];
Slotinfo[] slotInfo = new Slotinfo[slots.length];
for (var s : slots) { for (var s : slots) {
for (long b = s.lo; b != X; b &= b - 1) count[numberOfTrailingZeros(b)]++; for (long b = s.lo; b != X; b &= b - 1) count[numberOfTrailingZeros(b)]++;
for (long b = s.hi; b != X; b &= b - 1) count[64 | numberOfTrailingZeros(b)]++; for (long b = s.hi; b != X; b &= b - 1) count[64 | numberOfTrailingZeros(b)]++;
@@ -883,27 +888,23 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
for (int i = 0; i < slots.length; i++) { for (int i = 0; i < slots.length; i++) {
var slot = slots[i]; var slot = slots[i];
slotScores[i] = slotScore(count, slot.lo, slot.hi); slotScores[i] = slotScore(count, slot.lo, slot.hi);
slotInfo[i] = new Slotinfo(slot.key, slot.lo, slot.hi, slotScores[i], slot.entry);
} }
return slotInfo;
} }
public static FillResult fillMask(final Rng rng,final Slot[] slots,final Grid mask, final boolean multiThreaded) { public static FillResult fillMask(final Rng rng, final Slotinfo[] slots,
final Grid grid,
final boolean multiThreaded) {
val NO_LOG = (!Main.VERBOSE || multiThreaded); val NO_LOG = (!Main.VERBOSE || multiThreaded);
val grid = mask;
val used = new long[2048]; val used = new long[2048];
val assigned = new long[CLUE_INDEX_MAX_SIZE]; val assigned = new long[CLUE_INDEX_MAX_SIZE];
val bitset = new long[2500]; val bitset = new long[2500];
val g = grid.g; val g = grid.g;
val TOTAL = slots.length;
val TOTAL = slots.length; val t0 = System.currentTimeMillis();
val slotScores = new int[TOTAL]; val CARRIER = new Pick(null, null, 0);
scoreSlots(slotScores, slots);
val t0 = System.currentTimeMillis();
class Solver { class Solver {
private final Pick CARRIER = new Pick(null, null, 0);
long nodes; long nodes;
long backtracks; long backtracks;
int lastMRV; int lastMRV;
@@ -963,7 +964,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
return true; return true;
} }
void chooseMRV() { void chooseMRV() {
Slot best = null; Slotinfo best = null;
for (int i = 0, count, count2 = -1, bestScore = -1, n = TOTAL; i < n; i++) { for (int i = 0, count, count2 = -1, bestScore = -1, n = TOTAL; i < n; i++) {
var s = slots[i]; var s = slots[i];
if (assigned[s.key] != X) continue; if (assigned[s.key] != X) continue;
@@ -977,9 +978,9 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
} }
if (best == null if (best == null
|| count < count2 || count < count2
|| (count == count2 && slotScores[i] > bestScore)) { || (count == count2 && s.score > bestScore)) {
best = s; best = s;
bestScore = slotScores[i]; bestScore = s.score;
count2 = count; count2 = count;
if (count <= 1) break; if (count <= 1) break;
} }

View File

@@ -180,7 +180,9 @@ public class MainTest {
128L, 128L,
422762372923520L, 422762372923520L,
192L); 192L);
var filled = fillMask(rng, extractSlots(mask, dict.index()), mask.toGrid(), false); var slots = extractSlots(mask, dict.index());
val slotInfo = scoreSlots(new int[slots.length], slots);
var filled = fillMask(rng, slotInfo, mask.toGrid(), false);
Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)"); Assertions.assertTrue(filled.ok(), "Puzzle generation failed (not ok)");
Assertions.assertEquals(18, filled.wordCount(0), "Number of assigned words changed"); Assertions.assertEquals(18, filled.wordCount(0), "Number of assigned words changed");
Assertions.assertEquals("SLEDE", Lemma.asWord(filled.clueMap()[282])); Assertions.assertEquals("SLEDE", Lemma.asWord(filled.clueMap()[282]));