@iyulab/u-metaheur 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,32 +24,50 @@ u-metaheur provides generic implementations of common metaheuristic algorithms.
|
|
|
24
24
|
|
|
25
25
|
## Key Traits
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
// GA — implement these for your domain
|
|
29
|
-
trait Chromosome: Clone + Send + Sync {
|
|
30
|
-
fn fitness(&self) -> f64;
|
|
31
|
-
}
|
|
32
|
-
trait Crossover<C: Chromosome> {
|
|
33
|
-
fn crossover(&self, parent1: &C, parent2: &C, rng: &mut Rng) -> C;
|
|
34
|
-
}
|
|
35
|
-
trait Mutation<C: Chromosome> {
|
|
36
|
-
fn mutate(&self, chromosome: &mut C, rng: &mut Rng);
|
|
37
|
-
}
|
|
27
|
+
Each algorithm asks for one small trait from your domain:
|
|
38
28
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
29
|
+
| Algorithm | Implement | You provide |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| GA | `ga::GaProblem` (+ `ga::Individual`) | create, evaluate, crossover and mutate individuals |
|
|
32
|
+
| BRKGA | `brkga::BrkgaDecoder` | `decode(&[f64]) -> f64` — random keys to a cost |
|
|
33
|
+
| SA | `sa::SaProblem` | an initial solution, its `cost`, a `neighbor` |
|
|
34
|
+
| ALNS | `alns::AlnsProblem` + `DestroyOperator` / `RepairOperator` | a solution, its cost, destroy and repair moves |
|
|
35
|
+
|
|
36
|
+
Every cost is minimised.
|
|
45
37
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
```rust
|
|
39
|
+
use rand::{Rng, RngExt};
|
|
40
|
+
use u_metaheur::brkga::{BrkgaConfig, BrkgaDecoder, BrkgaRunner};
|
|
41
|
+
use u_metaheur::sa::{SaConfig, SaProblem, SaRunner};
|
|
42
|
+
|
|
43
|
+
// BRKGA: the decoder turns random keys into a cost -- here, how far the keys
|
|
44
|
+
// are from ascending order.
|
|
45
|
+
struct Sorted;
|
|
46
|
+
impl BrkgaDecoder for Sorted {
|
|
47
|
+
fn decode(&self, keys: &[f64]) -> f64 {
|
|
48
|
+
keys.windows(2).filter(|w| w[0] > w[1]).count() as f64
|
|
49
|
+
}
|
|
49
50
|
}
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
let config = BrkgaConfig::new(6).with_stagnation_limit(200).with_seed(7);
|
|
52
|
+
let result = BrkgaRunner::run(&Sorted, &config).unwrap();
|
|
53
|
+
assert_eq!(result.best_cost, 0.0);
|
|
54
|
+
|
|
55
|
+
// SA: minimise (x - 3)^2 by small random steps.
|
|
56
|
+
struct Parabola;
|
|
57
|
+
impl SaProblem for Parabola {
|
|
58
|
+
type Solution = f64;
|
|
59
|
+
fn initial_solution<R: Rng>(&self, _rng: &mut R) -> f64 {
|
|
60
|
+
0.0
|
|
61
|
+
}
|
|
62
|
+
fn cost(&self, x: &f64) -> f64 {
|
|
63
|
+
(x - 3.0).powi(2)
|
|
64
|
+
}
|
|
65
|
+
fn neighbor<R: Rng>(&self, x: &f64, rng: &mut R) -> f64 {
|
|
66
|
+
x + rng.random_range(-0.5..0.5)
|
|
67
|
+
}
|
|
52
68
|
}
|
|
69
|
+
let result = SaRunner::run(&Parabola, &SaConfig::default().with_seed(7));
|
|
70
|
+
assert!((result.best - 3.0).abs() < 0.1);
|
|
53
71
|
```
|
|
54
72
|
|
|
55
73
|
## Features
|
|
@@ -60,10 +78,10 @@ trait RepairOperator<S> {
|
|
|
60
78
|
|
|
61
79
|
```toml
|
|
62
80
|
[dependencies]
|
|
63
|
-
u-metaheur =
|
|
81
|
+
u-metaheur = "0.4"
|
|
64
82
|
|
|
65
83
|
# with serde support
|
|
66
|
-
u-metaheur = {
|
|
84
|
+
u-metaheur = { version = "0.4", features = ["serde"] }
|
|
67
85
|
```
|
|
68
86
|
|
|
69
87
|
## Build & Test
|
|
@@ -98,6 +116,27 @@ The package resolves per environment via a conditional `exports` map:
|
|
|
98
116
|
| Bundlers (webpack, Vite, …) | ESM + WebAssembly ESM-integration (`default` condition) |
|
|
99
117
|
| Node.js — `require()`, ESM `import`, CJS TS runners (`tsx`, `ts-node`) | CJS glue loading the wasm from the filesystem (`node` condition) — no loader hooks or flags |
|
|
100
118
|
|
|
119
|
+
### Quick Start
|
|
120
|
+
|
|
121
|
+
Both functions solve a travelling-salesman tour over `nodes` (`[x, y]` pairs)
|
|
122
|
+
and return the best tour found and its closed length:
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
import { run_ga, run_sa } from '@iyulab/u-metaheur';
|
|
126
|
+
|
|
127
|
+
// The corners of a unit square: the shortest closed tour is its perimeter, 4.
|
|
128
|
+
const nodes = [[0, 0], [1, 0], [1, 1], [0, 1]];
|
|
129
|
+
|
|
130
|
+
const ga = run_ga({ nodes, population_size: 30, generations: 50 });
|
|
131
|
+
const sa = run_sa({ nodes, iterations: 2000 });
|
|
132
|
+
console.log(ga.best_distance, ga.best_tour); // 4 [ ... ]
|
|
133
|
+
console.log(sa.best_distance, sa.iterations_run);
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
`run_ga` also takes `mutation_rate`; `run_sa` takes `initial_temp` and
|
|
137
|
+
`cooling_rate`. Every setting is optional except `nodes`, and a setting the
|
|
138
|
+
function does not have is rejected rather than ignored.
|
|
139
|
+
|
|
101
140
|
### TypeScript
|
|
102
141
|
|
|
103
142
|
Every exported function declares its parameter and return types, and the
|