Improve Generation Performance: Store states in HashMap and don't update the GraphData incrementally

This commit is contained in:
2025-08-30 15:39:07 +02:00
parent 4738e5f2d4
commit 478fa10afd
6 changed files with 90 additions and 52 deletions

View File

@ -18,6 +18,7 @@ import {
} from "./state.js";
import { DIRECTIONS, LEFT, RIGHT, UP, DOWN } from "../../constants.js";
import { HORIZONTAL, VERTICAL } from "../../constants.js";
import { key_of } from "../../main.js";
const initial_states = [
single,
@ -35,6 +36,8 @@ const generate = (states, initial_state, graph, previous_move) => {
let last_print = 0;
let data = graph.graphData();
while (stack.length > 0) {
const [current_state, prev_move] = stack.pop();
@ -45,7 +48,7 @@ const generate = (states, initial_state, graph, previous_move) => {
const states_before = states.length;
const [new_state, new_block] = move(
states,
graph,
data,
current_state,
block,
direction,
@ -62,6 +65,8 @@ const generate = (states, initial_state, graph, previous_move) => {
}
}
}
graph.graphData(data);
};
const select = (state, offsetX, offsetY) => {
@ -84,7 +89,7 @@ const select = (state, offsetX, offsetY) => {
return null;
};
const move = (states, graph, state, block, direction) => {
const move = (states, data, state, block, direction) => {
if (
block[1] === HORIZONTAL &&
(arrays_are_equal(direction, DIRECTIONS[UP]) ||
@ -112,33 +117,29 @@ const move = (states, graph, state, block, direction) => {
// insert_block(new_state, block);
let new_state = structuredClone(state);
delete new_state.name;
let new_block = move_block(block, direction);
move_state_block(new_state, block, direction);
// TODO: Make states into a hashmap?
let index = index_of_state(states, new_state);
let new_link = null;
let new_node = null;
if (index !== null) {
if (states.has(new_state)) {
// We already had this state, just generate a link
new_link = {
source: index_of_state(states, state), // We're coming from this state...
target: index, // ...and ended up here, at a previous state.
source: key_of(state), // We're coming from this state...
target: key_of(new_state), // ...and ended up here, at a previous state.
};
} else {
states.push(new_state);
states.add(new_state);
new_node = {
id: states.length - 1,
id: key_of(new_state),
};
new_link = {
source: index_of_state(states, state), // We're coming from this state...
target: states.length - 1, // ...and ended up here, at a new state.
source: key_of(state), // We're coming from this state...
target: key_of(new_state), // ...and ended up here, at a new state.
};
}
const data = graph.graphData();
// TODO: Faster without this?
const has_link = (data, link) => {
// for (let l of data.links) {
@ -154,15 +155,10 @@ const move = (states, graph, state, block, direction) => {
};
if (new_node !== null) {
graph.graphData({
nodes: [...data.nodes, new_node],
links: [...data.links, new_link],
});
data.nodes.push(new_node);
data.links.push(new_link);
} else if (!has_link(data, new_link)) {
graph.graphData({
nodes: data.nodes,
links: [...data.links, new_link],
});
data.links.push(new_link);
}
return [new_state, new_block];