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