🚀 benchmark ?

This commit is contained in:
platane
2020-10-06 23:53:46 +02:00
committed by Platane
parent b0784fbaca
commit 16a47349be
10 changed files with 181 additions and 11 deletions

View File

@@ -18,6 +18,7 @@
"type": "tsc --noEmit",
"lint": "yarn prettier -c '**/*.{ts,js,json,md,yml,yaml}' '!packages/action/dist/**' '!packages/demo/dist/**' '!packages/demo/webpack.config.js'",
"test": "jest --verbose --passWithNoTests --no-cache",
"dev:demo": "( cd packages/demo ; yarn dev )",
"build:demo": "( cd packages/demo ; yarn build )",
"build:action": "( cd packages/action ; yarn build )"
}

View File

@@ -19,6 +19,16 @@ setColor(corner, 4, 0, 1 as Color);
setColor(corner, 4, 4, 1 as Color);
setColor(corner, 0, 0, 1 as Color);
// enclaved color
export const enclave = createEmptyGrid(7, 7);
setColor(enclave, 3, 4, 2 as Color);
setColor(enclave, 2, 3, 2 as Color);
setColor(enclave, 2, 4, 2 as Color);
setColor(enclave, 4, 4, 2 as Color);
setColor(enclave, 4, 3, 2 as Color);
setColor(enclave, 3, 3, 1 as Color);
setColor(enclave, 5, 5, 1 as Color);
const create = (width: number, height: number, emptyP: number) => {
const grid = createEmptyGrid(width, height);
const random = new ParkMiller(10);
@@ -31,3 +41,7 @@ const create = (width: number, height: number, emptyP: number) => {
export const small = create(10, 7, 3);
export const smallPacked = create(10, 7, 1);
export const smallFull = create(10, 7, 0);
// small realistic
export const realistic = create(52, 7, 3);
export const realisticFull = create(52, 7, 0);

View File

@@ -0,0 +1,33 @@
import { getAvailableInterestingRoutes } from "../getAvailableRoutes";
import { small as grid } from "../__fixtures__/grid";
import { snake3 } from "../__fixtures__/snake";
import { performance } from "perf_hooks";
import { getAvailableRoutes } from "../getAvailableRoutes2";
const m = 1000;
{
const s = performance.now();
for (let k = m; k--; ) {
const solutions = [];
getAvailableInterestingRoutes(
grid,
snake3,
(snakes) => {
solutions.push(snakes);
return false;
},
2
);
}
console.log((performance.now() - s) / m, "ms");
}
{
const s = performance.now();
for (let k = m; k--; ) {
getAvailableRoutes(grid, snake3, 2);
}
console.log((performance.now() - s) / m, "ms");
}

View File

@@ -0,0 +1,65 @@
import { Grid, isInsideLarge, getColor, isInside, isEmpty } from "./grid";
import { around4 } from "./point";
import {
getHeadX,
getHeadY,
nextSnake,
Snake,
snakeEquals,
snakeWillSelfCollide,
} from "./snake";
const snakeEqualsN = (a: Snake, b: Snake, n = a.length / 2) => {
for (let i = 0; i < n * 2; i++) if (a[i] !== b[i]) return false;
return true;
};
export const getAvailableRoutes = (grid: Grid, snake0: Snake, n?: number) => {
const openList: Snake[][] = [[snake0]];
const closeList: Snake[] = [];
const solutions: Snake[][] = [];
while (openList.length) {
const c = openList.shift()!;
const [snake] = c;
closeList.push(snake);
const cx = getHeadX(snake);
const cy = getHeadY(snake);
for (let i = 0; i < around4.length; i++) {
const { x: dx, y: dy } = around4[i];
const nx = cx + dx;
const ny = cy + dy;
if (
isInsideLarge(grid, 1, nx, ny) &&
!snakeWillSelfCollide(snake, dx, dy)
) {
const nsnake = nextSnake(snake, dx, dy);
if (!closeList.some((s) => snakeEquals(nsnake, s))) {
const color = isInside(grid, nx, ny) && getColor(grid, nx, ny);
if (color && !isEmpty(color)) {
if (solutions.every(([s]) => !snakeEqualsN(s, nsnake, n))) {
const solution = [nsnake, ...c.slice(0, -1)];
solutions.push(solution);
}
} else {
if (!openList.some(([s]) => snakeEquals(nsnake, s))) {
const chain = [nsnake, ...c];
openList.push(chain);
openList.sort((a, b) => a.length - b.length);
}
}
}
}
}
}
return solutions;
};

View File

@@ -20,6 +20,8 @@ const createHeuristic = (grid0: Grid) => {
colorCount[color] = (0 | colorCount[color]) + 1;
}
// const colors = Object.keys(colorCount).map((x) => +x);
const target = Object.entries(colorCount)
.sort(([a], [b]) => +a - +b)
.map(([color, length]: any) => Array.from({ length }, () => +color))
@@ -33,9 +35,22 @@ const createHeuristic = (grid0: Grid) => {
_snake: Snake,
stack: Color[]
) => {
const x = target[stack.length];
const colorTarget = target[stack.length];
return (c: Color) => (x === c ? 1 : 0);
// const cc = { ...colorCount };
// for (const color of stack) cc[color]--;
// let colorTarget;
// for (let i = colors.length; i--; )
// if (cc[colors[i]] > 0) colorTarget = colors[i];
return (c: Color) => {
if (colorTarget === c) return 1;
return 0;
// return 1 - Math.abs(colorTarget - c) / 10;
};
};
const isEnd = (_grid: Grid, _snake: Snake, stack: Color[]) =>

View File

@@ -15,8 +15,6 @@ const { canvas, draw } = createCanvas(grid);
document.body.appendChild(canvas);
const onChange = () => {
debugger;
const grid0 = copyGrid(grid);
const stack0: Color[] = [];
let snake0 = snake;

View File

@@ -0,0 +1,21 @@
import * as grid from "@snk/compute/__fixtures__/grid";
const container = document.createElement("div");
container.style.fontFamily = "helvetica";
document.body.appendChild(container);
for (const demo of ["getAvailableRoutes", "getBestRoute"]) {
const title = document.createElement("h1");
title.innerText = demo;
container.appendChild(title);
for (const g of Object.keys(grid)) {
const a = document.createElement("a");
a.style.display = "block";
a.innerText = `${demo} - ${g}`;
a.href = `/demo-${demo}.html?grid=${g}`;
container.appendChild(a);
}
}

View File

@@ -13,6 +13,7 @@ const config: Configuration = {
entry: {
"demo.getAvailableRoutes": "./demo.getAvailableRoutes",
"demo.getBestRoute": "./demo.getBestRoute",
"demo.index": "./demo.index",
},
resolve: { extensions: [".ts", ".js"] },
output: {
@@ -36,6 +37,10 @@ const config: Configuration = {
],
},
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
chunks: ["demo.index"],
}),
new HtmlWebpackPlugin({
filename: "demo-getAvailableRoutes.html",
chunks: ["demo.getAvailableRoutes"],

View File

@@ -13,6 +13,25 @@ type Options = {
sizeBorderRadius: number;
};
export const drawStack = (
ctx: CanvasRenderingContext2D,
stack: Color[],
max: number,
width: number,
o: { colorDots: Record<Color, string> }
) => {
ctx.save();
const m = width / max;
for (let i = 0; i < stack.length; i++) {
// @ts-ignore
ctx.fillStyle = o.colorDots[stack[i]];
ctx.fillRect(i * m, 0, m + width * 0.005, 10);
}
ctx.restore();
};
export const drawWorld = (
ctx: CanvasRenderingContext2D,
grid: Grid,
@@ -28,15 +47,13 @@ export const drawWorld = (
ctx.restore();
const m = 5;
ctx.save();
ctx.translate(o.sizeCell, (grid.height + 4) * o.sizeCell);
for (let i = 0; i < stack.length; i++) {
// @ts-ignore
ctx.fillStyle = o.colorDots[stack[i]];
ctx.fillRect(i * m, 0, m, 10);
}
const max = grid.data.reduce((sum, x) => sum + +!!x, stack.length);
drawStack(ctx, stack, max, grid.width * o.sizeCell, o);
ctx.restore();
// ctx.save();

View File

@@ -29,6 +29,7 @@ for (const key of [
"corner",
"small",
"smallPacked",
"enclave",
] as const)
it(`should generate ${key} gif`, async () => {
const grid = grids[key];