Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
c1ad1f8
Modern scafold project
benjides Nov 16, 2025
8902a18
Add test it sorts values on creation
benjides Nov 16, 2025
c914142
Add insert and tests
benjides Nov 16, 2025
a2319db
Add test it inserts value at first position
benjides Nov 16, 2025
05f69c4
Add test it inserts value at the middle position
benjides Nov 16, 2025
c9c53ba
test it inserts after in case of same priority
benjides Nov 16, 2025
f91d2ae
format:fix
benjides Nov 16, 2025
38d9243
Replace Month with Person type
benjides Nov 16, 2025
783e6ce
Make PriorityQueue receive priorityNodes
benjides Nov 17, 2025
7a4cd75
Add --fix flag to lint:fix script
benjides Nov 17, 2025
7c754e5
export node function to create PriorityNodes
benjides Nov 17, 2025
3077390
Reorganize tests
benjides Nov 17, 2025
f52be7f
Add poll PriorityQueue function and tests
benjides Nov 17, 2025
a07ef22
test it polls empty PriorityQueue and fix impl
benjides Nov 17, 2025
d055e34
Add HashSet and tests
benjides Nov 18, 2025
17266a9
Use assert for type enforcing
benjides Nov 18, 2025
a78ffc7
Organise tests
benjides Nov 18, 2025
36f7555
Add documentation for HashSet.insert
benjides Nov 18, 2025
7792dfe
Organize tests
benjides Nov 18, 2025
9709228
Use assert for type enforcing
benjides Nov 18, 2025
385d410
Add DepthFirstSearch intial impl
benjides Nov 18, 2025
f6ac737
test it solves after expanding once
benjides Nov 19, 2025
d022723
test it solves after expanding twice
benjides Nov 19, 2025
5ab4dbc
Reorganise teests
benjides Nov 19, 2025
07b1629
test it solves after expanding multiple states
benjides Nov 19, 2025
51d227b
test it solves after expanding multiple states filtering invalid move…
benjides Nov 19, 2025
5d99060
Fix priority for DepthFirstSearch
benjides Nov 19, 2025
11525b5
test it solves filtering already visited states
benjides Nov 19, 2025
2e4b766
refactor: remove unused variable
benjides Nov 19, 2025
1a5fd4d
refactor: reorganise tests
benjides Nov 19, 2025
658e568
refactor: extract gridSize constant
benjides Nov 19, 2025
e1bfb39
Add missing grid movement
benjides Nov 19, 2025
0dbc260
Rename test
benjides Nov 19, 2025
3363c47
Extract Grid.ts for testing
benjides Nov 20, 2025
a4d6e49
Add Grid type to create Expand<Position> dynamically
benjides Nov 20, 2025
25b7e3a
Add Grid type to create Expand<Position> dynamically
benjides Nov 20, 2025
95dcc26
Adjust tests
benjides Nov 20, 2025
1164943
Add test it solves worst solution
benjides Nov 20, 2025
0c49a0b
Add Tree impl and tests
benjides Nov 21, 2025
6159d9b
Use Tree to represent Search states
benjides Nov 21, 2025
27fd9e1
Use Namespaced imports
benjides Nov 21, 2025
671f070
Rename Tree constructor to fromRoot
benjides Nov 21, 2025
f24be4f
Map to insertable Tree.Nodes resulting states
benjides Nov 21, 2025
d995f89
Map to priorityNodes Tree.Nodes resulting states
benjides Nov 21, 2025
e035920
Create Tree Nodes with inverse key to avoid negating priorityQueue nodes
benjides Nov 21, 2025
808f043
Use Array reduce to insert nodes into PriorityQueue
benjides Nov 22, 2025
cc6dfe7
Use namespace types
benjides Nov 22, 2025
d092f93
Add expand constant
benjides Nov 22, 2025
9c44205
test it filters already visited states on expanding
benjides Nov 22, 2025
de01f57
Use expand for tests and remove unused expandPosition
benjides Nov 22, 2025
cfd65d3
Typo
benjides Nov 23, 2025
d16a9c5
Remove sort priority nodes on creation unused use case
benjides Nov 23, 2025
68440ce
Change PriorityQueue.insert signature to receive priority and data pairs
benjides Nov 23, 2025
6cab237
Use manual inserts on PriorityQueue for tests
benjides Nov 23, 2025
e0d824d
Remove unused symbol and add types to exported symbols
benjides Nov 23, 2025
ce4c589
Add empty constructor
benjides Nov 23, 2025
3971d55
Remove unused symbol
benjides Nov 23, 2025
76dec6a
Add PriorityQueue.of constructor method
benjides Nov 23, 2025
70b66b2
Remove unused export
benjides Nov 23, 2025
187c1e3
Add docs
benjides Nov 23, 2025
0629eac
Remove extension from imported files
benjides Nov 23, 2025
466e005
Add docs
benjides Nov 23, 2025
1604b99
Fine tune types
benjides Nov 23, 2025
d20acee
Remove Child and Root types from Tree
benjides Nov 23, 2025
5b90547
Convert expandRecursively to constant
benjides Nov 23, 2025
e4f1e51
Move expandRecursively outside depthFirstSearch declaration
benjides Nov 23, 2025
cb9ca48
Inline constants
benjides Nov 23, 2025
435b5fb
Add State<S> type to represent a Search exploration status and usage
benjides Nov 29, 2025
92b015c
Add isDone function to check if State has reached goal
benjides Nov 29, 2025
d04b5f3
Use state for expandRecursively
benjides Nov 29, 2025
45a306a
Extract expandNewStates constant
benjides Jan 18, 2026
3357461
Extract isGoal parameter
benjides Jan 19, 2026
5856ec6
Introduce expandNewStates parameter
benjides Jan 19, 2026
5363138
Remove unused parameters
benjides Jan 19, 2026
ab4e5a1
Extract isGoal parameter
benjides Jan 21, 2026
337848c
Extract persons constants
benjides Jan 21, 2026
ae4b837
Introduce insertPerson constant
benjides Jan 21, 2026
6b9c232
Add Graph and tests
benjides Feb 1, 2026
2cf935c
Cleanup
benjides Feb 1, 2026
3a0d780
Use Node alias
benjides Feb 2, 2026
380206a
Add OpenSet<S> type alias of PriorityQueue<Node<S>>
benjides Feb 2, 2026
18c0f9c
Do not export isDone
benjides Feb 2, 2026
ce48fad
Use isDone with S type directly
benjides Feb 2, 2026
a600fd0
Replace Tree usages with Node
benjides Feb 2, 2026
15e6260
Extract nodeOrd const
benjides Feb 2, 2026
559af70
Remove exported toArray const
benjides Feb 2, 2026
a281180
Extract nodeInsert const
benjides Feb 2, 2026
0258f51
Extract hasBeenVisited const
benjides Feb 2, 2026
29ab53a
Use hasBeenVisited const
benjides Feb 2, 2026
7f0aed2
Inline expandNewStates constant
benjides Feb 2, 2026
83214d4
refactoring
benjides Feb 2, 2026
67d01b6
Extract ClosedSet type alias
benjides Feb 2, 2026
a932c0f
Extract openSet constructor
benjides Feb 2, 2026
676e06d
Extract closedSet constructor
benjides Feb 2, 2026
58f69f1
Rename var
benjides Feb 2, 2026
5a552bd
Add toNode constructor
benjides Feb 2, 2026
321c561
Extract Node class
benjides Feb 2, 2026
41b7608
Replace * imports for HashSet
benjides Feb 2, 2026
aeddd8e
Rename HashSet.empty to hashSet
benjides Feb 2, 2026
1229c4c
Rename PriorityQueue.of to priorityQueue
benjides Feb 2, 2026
78c7035
Fix hashSet references
benjides Feb 2, 2026
7b74145
Replace * imports for PriorityQueue
benjides Feb 2, 2026
5241def
Rename variables
benjides Feb 2, 2026
a2d71f8
Add evaluationFunction for Node creation
benjides Feb 2, 2026
42cf7ec
Extract evaluate type
benjides Feb 2, 2026
3020b26
Extract search constant
benjides Feb 2, 2026
c725ba5
Extract Search file
benjides Feb 2, 2026
a36067b
Add BestFirstSearch and tests
benjides Feb 3, 2026
b8a8365
Reformat
benjides Feb 3, 2026
cb0870d
Add return type
benjides Feb 3, 2026
4ceee43
Add Node.depth property
benjides Feb 3, 2026
345f412
Use Evaluate<S> for Ord<Node<S>>
benjides Feb 3, 2026
ecb7ec0
Remove Node<S> key field
benjides Feb 3, 2026
b7b2504
Simplify node function
benjides Feb 3, 2026
fcf79f1
Add generic typings to Search<S>
benjides Feb 4, 2026
df14e79
Add AStar and tests
benjides Feb 4, 2026
8ba1c5e
Fix AStar tests
benjides Feb 4, 2026
3add4c2
Introduce solver and Search type
benjides Feb 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions .babelrc

This file was deleted.

15 changes: 0 additions & 15 deletions .eslintrc.json

This file was deleted.

5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"singleQuote": true,
"semi": false,
"trailingComma": "all"
}
6 changes: 2 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

language: node_js
node_js:
- node
Expand All @@ -7,10 +6,9 @@ before_deploy:
after_success:
- 'bash <(curl -s https://codecov.io/bash)'
deploy:
skip_cleanup: true
provider: npm
email: "$NPM_EMAIL"
api_key: "$NPM_TOKEN"
email: '$NPM_EMAIL'
api_key: '$NPM_TOKEN'
skip_cleanup: true
on:
tags: true
167 changes: 87 additions & 80 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Maizal

<p align="center"><img width="200"src="maizal.png?raw=true"></p>

> Pronounced like /'māisɔːl/
Expand All @@ -19,6 +20,7 @@ $ npm install maizal
```

In the browser

```
<script src="https://unpkg.com/maizal/dist/maizal.min.js"></script>
```
Expand All @@ -28,40 +30,42 @@ In the browser
Perform a `Breadth-first` search

```js
const maizal = require('maizal');
const maizal = require('maizal')

maizal.bfs({
initial: {
position: 1,
},
goals: {
position: 4,
},
actions: [
{
name: 'right',
expand: (state) => {
if (state.position + 1 > 5) return undefined;
return { position: state.position + 1 };
},
maizal
.bfs({
initial: {
position: 1,
},
{
name: 'left',
expand: (state) => {
if (state.position - 1 < 0) return undefined;
return { position: state.position - 1 };
},
goals: {
position: 4,
},
],
hash: 'position',
})
.then(results => console.log(results))
.catch(error => console.log(error));
actions: [
{
name: 'right',
expand: (state) => {
if (state.position + 1 > 5) return undefined
return { position: state.position + 1 }
},
},
{
name: 'left',
expand: (state) => {
if (state.position - 1 < 0) return undefined
return { position: state.position - 1 }
},
},
],
hash: 'position',
})
.then((results) => console.log(results))
.catch((error) => console.log(error))
```

Perform a `Dijkstra` search

```js
const maizal = require('maizal');
const maizal = require('maizal')

const config = {
initial: {
Expand All @@ -75,15 +79,15 @@ const config = {
name: 'right',
cost: 50,
expand: (state) => {
if (state.position + 1 > 5) return undefined;
return { position: state.position + 1 };
if (state.position + 1 > 5) return undefined
return { position: state.position + 1 }
},
},
{
name: 'left',
expand: (state) => {
if (state.position - 1 < 0) return undefined;
return { position: state.position - 1 };
if (state.position - 1 < 0) return undefined
return { position: state.position - 1 }
},
},
],
Expand All @@ -92,117 +96,119 @@ const config = {

async function solveCorridor() {
try {
const results = await maizal.dijkstra(config);
console.log(results);
const results = await maizal.dijkstra(config)
console.log(results)
} catch (error) {
console.error(error);
console.error(error)
}
}
```

> **NOTE:** `async/await` is part of ECMAScript 2017 and is not supported in Internet
> Explorer and older browsers, so use with caution.


## Documentation

The config object

### Initial state

| Type | Defaults | Optional | Description |
|--------|----------|----------|-----------------------------|
| ------ | -------- | -------- | --------------------------- |
| Object | | false | Initial state of the search |

Examples

```js
const initial = {
position: [4, 5],
};
}

const initial = {
name: 'myFancyName',
};
}
```

### Goals

| Type | Defaults | Optional | Description |
|--------|----------|----------|-----------------------------|
| Type | Defaults | Optional | Description |
| --------------- | -------- | -------- | ------------------- |
| Object \| Array | | false | Set of goals states |

Examples

```js
const goals = [
{
position: [10, 12],
},
{
position: [4, 2],
}
];
},
]

const goals = {
height: 200,
};
}
```

### Actions

| Type | Defaults | Optional | Description |
|--------|----------|----------|-----------------------------|
| Type | Defaults | Optional | Description |
| --------------- | -------- | -------- | ----------------------------------------- |
| Object \| Array | | false | Set of actions to take for each new state |

|Key | Type | Defaults | Optional | Description |
|-------|-----------|----------|----------|-----------------------------|
|name | String | 'expand' | true | Action name |
|cost | Int | 1 | true | Action cost |
|expand | Function | | false | Function that takes a state as argument and returns the data for the following states |
| Key | Type | Defaults | Optional | Description |
| ------ | -------- | -------- | -------- | ------------------------------------------------------------------------------------- |
| name | String | 'expand' | true | Action name |
| cost | Int | 1 | true | Action cost |
| expand | Function | | false | Function that takes a state as argument and returns the data for the following states |

Examples

```js
const actions = [
{
expand: (state) => {
return { position: state.position + 1 };
}
return { position: state.position + 1 }
},
},
{
expand: (state) => {
return Promise.resolve({ position: state.position - 1});
}
return Promise.resolve({ position: state.position - 1 })
},
},
{
name: 'myFancyAction',
cost: 80,
expand: (state) => {
if(state.height > 90) {
return;
if (state.height > 90) {
return
}
return { height: state.height + 10 };
}
return { height: state.height + 10 }
},
},
];

]
```

> **NOTE:** Remember to return `undefined` or simply `return` on forbidden actions to avoid generating infinite states

### Hash

Used to establish when two newly generated states are essentially the same , for example, in a maze going to the left one cell and the returning to the same represents essentially the same state and we do not want that

| Type | Defaults | Optional | Description |
|--------|----------|----------|-----------------------------|
| String\|Function| | false | Field or function to determine the equality of two states |
| Type | Defaults | Optional | Description |
| ---------------- | -------- | -------- | --------------------------------------------------------- |
| String\|Function | | false | Field or function to determine the equality of two states |

Examples

```js
const hash = 'position';
const hash = 'position'

const hash = 'height';
const hash = 'height'

const hash = (state) => `${state.x},${state.y}`;
const hash = (state) => `${state.x},${state.y}`
```

### Heuristics
Expand All @@ -211,24 +217,24 @@ Used to give a state a 'sense of approaching to the goal'.
It is a function that returns decreasing values as the closer we get to the goal.
It depends purely on your search state representation and you must ensure to provide logical and decreasing values the closer the solution is

| Type | Defaults | Optional | Description |
|--------|----------|----------|-----------------------------|
|Function| | true | Function to determine the 'proximity' to a goal |
| Type | Defaults | Optional | Description |
| -------- | -------- | -------- | ----------------------------------------------- |
| Function | | true | Function to determine the 'proximity' to a goal |

Examples

```js
const heuristics = ({ x, y }) => {
// Euclidean distance
return Math.sqrt(((x - goal.x) ** 2) + ((y - goal.y) ** 2));
};
return Math.sqrt((x - goal.x) ** 2 + (y - goal.y) ** 2)
}

const heuristics = ({ x, y }) => {
// Manhattan distance
return Math.abs((x - goal.x) + (y - goal.y));
};
return Math.abs(x - goal.x + (y - goal.y))
}

const heuristics = state => 90 - state.position;
const heuristics = (state) => 90 - state.position
```

A better documentation its on the way.
Expand All @@ -238,20 +244,21 @@ A better documentation its on the way.
Available engines

### Uninformed

| Engine | API |
|---------------|----------|
| ------------- | -------- |
| Breadth-first | bfs |
| Dijkstra | dijkstra |
| Random-search | random |
| Depth-first | dfs |

### Informed
| Engine | API |
|-------------------|----------|
| Best-first search | bestfs |
| A* | astar |
| Weighted-A* | weightedastar |

| Engine | API |
| ----------------- | ------------- |
| Best-first search | bestfs |
| A\* | astar |
| Weighted-A\* | weightedastar |

## Promises

Expand Down
Loading