introduce bitloops
This commit is contained in:
@@ -50,9 +50,9 @@ public final class CsvIndexService
|
||||
var parts = line.split(",", 5);
|
||||
var id = Integer.parseInt(parts[0].trim());
|
||||
var word = parts[1].trim();
|
||||
if (!word.matches("^[A-Z]{2,8}$")) {
|
||||
/* if (!word.matches("^[A-Z]{2,8}$")) {
|
||||
throw new RuntimeException("Invalid word:" + line);
|
||||
}
|
||||
}*/
|
||||
|
||||
int score = Integer.parseInt(parts[2].trim());
|
||||
if (score < 1) {
|
||||
@@ -133,8 +133,7 @@ public final class CsvIndexService
|
||||
throw new IndexOutOfBoundsException("lineIndex=" + lineIndex + ", max=" + (local.length - 1));
|
||||
}
|
||||
|
||||
var start = local[lineIndex];
|
||||
csvChannel.position(start);
|
||||
long currentPos = local[lineIndex];
|
||||
|
||||
// lees in blokjes (sneller dan 1 byte) tot newline
|
||||
var buf = new byte[8192];
|
||||
@@ -143,17 +142,15 @@ public final class CsvIndexService
|
||||
|
||||
while (true) {
|
||||
var bb = ByteBuffer.wrap(buf);
|
||||
var n = csvChannel.read(bb);
|
||||
var n = csvChannel.read(bb, currentPos);
|
||||
if (n < 0) break; // EOF
|
||||
currentPos += n;
|
||||
var end = n;
|
||||
|
||||
for (var i = 0; i < end; i++) {
|
||||
var b = buf[i];
|
||||
|
||||
if (b == (byte) '\n') {
|
||||
// reposition kanaal op byte na newline
|
||||
long back = (end - i - 1);
|
||||
csvChannel.position(csvChannel.position() - back);
|
||||
return new String(out, 0, total, StandardCharsets.UTF_8);
|
||||
}
|
||||
if (b == (byte) '\r') continue;
|
||||
@@ -194,10 +191,10 @@ public final class CsvIndexService
|
||||
try (var ch = FileChannel.open(path, StandardOpenOption.READ)) {
|
||||
var offs = new long[131072]; // start-capacity, groeit indien nodig
|
||||
var c = 0;
|
||||
offs[c++] = 0L;
|
||||
offs[c++] = 0;
|
||||
|
||||
var buf = ByteBuffer.allocateDirect(1 << 20);
|
||||
long pos = 0;
|
||||
var buf = ByteBuffer.allocateDirect(1 << 20);
|
||||
int pos = 0;
|
||||
|
||||
while (true) {
|
||||
buf.clear();
|
||||
@@ -230,8 +227,7 @@ public final class CsvIndexService
|
||||
|
||||
public static long[] readIndex(Path in) throws IOException {
|
||||
try (var dis = new DataInputStream(new BufferedInputStream(Files.newInputStream(in)))) {
|
||||
var magic = dis.readInt();
|
||||
if (magic != MAGIC) throw new IOException("Not a LIDX file");
|
||||
if (dis.readInt() != MAGIC) throw new IOException("Not a LIDX file");
|
||||
|
||||
var version = dis.readInt();
|
||||
if (version != VERSION) throw new IOException("Unsupported version: " + version);
|
||||
|
||||
@@ -44,16 +44,16 @@ public class Main {
|
||||
public static class Opts {
|
||||
|
||||
public int seed = (int) (System.nanoTime() ^ System.currentTimeMillis());
|
||||
public int clueSize = 24;
|
||||
public int clueSize = 20;
|
||||
public int pop = 40;
|
||||
public int offspring = 60;
|
||||
public int gens = 700;
|
||||
public int gens = 500;
|
||||
public String wordsPath = "nl_score_hints_v3.csv";
|
||||
public double minSimplicity = 0; // 0 means no limit
|
||||
public int threads = Math.max(1, Runtime.getRuntime().availableProcessors());
|
||||
public int tries = threads;
|
||||
public boolean reindex = false;
|
||||
public boolean verbose = false;
|
||||
public boolean verbose = true;
|
||||
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ public class Main {
|
||||
--clues 18
|
||||
--pop 40
|
||||
--offspring 60
|
||||
--gens 700
|
||||
--gens 500
|
||||
--words nl_score_hints.csv
|
||||
--min-simplicity 0 (no limit)
|
||||
--threads %d
|
||||
@@ -286,9 +286,10 @@ public class Main {
|
||||
|
||||
try {
|
||||
// Keep at least some tasks in flight
|
||||
final var service = CsvIndexService.SC.get();
|
||||
for (int i = 0; i < opts.threads; i++) {
|
||||
final int attempt = ++submitted;
|
||||
completionService.submit(() -> attempt(new Rng(opts.seed + attempt), dict, opts));
|
||||
final int attemptIdx = ++submitted;
|
||||
completionService.submit(() -> ScopedValue.where(CsvIndexService.SC, service).call(() -> attempt(new Rng(opts.seed + attemptIdx), dict, opts)));
|
||||
}
|
||||
|
||||
while (System.currentTimeMillis() < deadline) {
|
||||
@@ -304,8 +305,8 @@ public class Main {
|
||||
|
||||
// Submit another task if we still have time
|
||||
if (System.currentTimeMillis() < deadline) {
|
||||
final int attempt = ++submitted;
|
||||
completionService.submit(() -> attempt(new Rng(opts.seed + attempt), dict, opts));
|
||||
final int attemptIdx = ++submitted;
|
||||
completionService.submit(() -> ScopedValue.where(CsvIndexService.SC, service).call(() -> attempt(new Rng(opts.seed + attemptIdx), dict, opts)));
|
||||
}
|
||||
}
|
||||
if (resFinal == null) warn("status : UNSOLVED (timeout)");
|
||||
@@ -316,6 +317,11 @@ public class Main {
|
||||
warn("status : ERROR (" + e.getMessage() + ")");
|
||||
} finally {
|
||||
executor.shutdownNow();
|
||||
try {
|
||||
executor.awaitTermination(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -369,9 +375,11 @@ public class Main {
|
||||
}
|
||||
}
|
||||
static PuzzleResult _attempt(Rng rng, Dict dict, Opts opts) {
|
||||
long t0 = System.currentTimeMillis();
|
||||
TOTAL_ATTEMPTS.incrementAndGet();
|
||||
var swe = new SwedishGenerator(rng, new int[STACK_SIZE], Clues.createEmpty());
|
||||
var mask = swe.generateMask(opts.clueSize, opts.pop, opts.gens, Math.max(opts.offspring, (int) Math.floor(1.5 * opts.pop)));
|
||||
var mask = swe.generateMask(opts.clueSize, opts.pop, opts.gens, opts.offspring);
|
||||
if (mask == null) return null;
|
||||
|
||||
var filled = fillMask(rng, extractSlots(mask, dict.index()), mask.toGrid());
|
||||
|
||||
@@ -387,10 +395,11 @@ public class Main {
|
||||
var status = filled.ok() ? "SUCCESS" : "FAILED";
|
||||
var simplicity = String.format(Locale.ROOT, "%.2f", filled.stats().simplicity);
|
||||
var nps = (int) (filled.stats().nodes / Math.max(0.001, filled.stats().seconds));
|
||||
var totalTime = (System.currentTimeMillis() - t0) / 1000.0;
|
||||
|
||||
System.out.printf(Locale.ROOT,
|
||||
"[ATTEMPT] thread=%s | status=%s | nodes=%d | backtracks=%d | nps=%d | simplicity=%s | time=%.1fs%n",
|
||||
name, status, filled.stats().nodes, filled.stats().backtracks, nps, simplicity, filled.stats().seconds
|
||||
name, status, filled.stats().nodes, filled.stats().backtracks, nps, simplicity, totalTime
|
||||
);
|
||||
|
||||
if (filled.ok() && (opts.minSimplicity <= 0 || filled.stats().simplicity >= opts.minSimplicity)) {
|
||||
|
||||
@@ -687,6 +687,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
||||
if (Main.VERBOSE) System.out.println("generateMask init pop: " + popSize + " clueSize: " + clueSize);
|
||||
var pop = new ArrayList<GridAndFit>();
|
||||
for (var i = 0; i < popSize; i++) {
|
||||
if (Thread.currentThread().isInterrupted()) return null;
|
||||
pop.add(new GridAndFit(hillclimb(randomMask(clueSize), clueSize, 180)));
|
||||
}
|
||||
|
||||
@@ -695,6 +696,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
||||
var children = new ArrayList<GridAndFit>();
|
||||
|
||||
for (var k = 0; k < offspring; k++) {
|
||||
if (Thread.currentThread().isInterrupted()) break;
|
||||
var p1 = pop.get(rng.randint(0, pop.size() - 1));
|
||||
var p2 = pop.get(rng.randint(0, pop.size() - 1));
|
||||
var child = crossover(p1.grid, p2.grid);
|
||||
@@ -720,6 +722,7 @@ public record SwedishGenerator(Rng rng, int[] stack, Clues cache) {
|
||||
|
||||
if (Main.VERBOSE && (gen & 15) == 15) System.out.println(" gen " + gen + "/" + gens + " bestFitness=" + pop.get(0).fit());
|
||||
}
|
||||
if (pop.isEmpty()) return null;
|
||||
GridAndFit best = pop.get(0);
|
||||
for (int i = 1; i < pop.size(); i++) {
|
||||
var x = pop.get(i);
|
||||
|
||||
Reference in New Issue
Block a user