Skip to content

Commit 2bda725

Browse files
authored
Merge pull request #18 from ewohltman/update-benchmarks
Update benchmarks
2 parents 5a27383 + 5533b52 commit 2bda725

9 files changed

Lines changed: 121 additions & 78 deletions

File tree

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Rust
1+
name: CI
22
on:
33
push:
44
branches: [ "main" ]
@@ -18,5 +18,5 @@ jobs:
1818
run: cargo clippy
1919
- name: Run tests
2020
run: cargo test
21-
- name: Build release binary
21+
- name: Build binary
2222
run: cargo build --release

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "genetic-sudoku"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
edition = "2024"
55
authors = ["Eric Wohltman <eric.wohltman@gmail.com>", "Bart Massey <bart@cs.pdx.edu>"]
66
repository = "https://github.com/ewohltman/genetic-sudoku"
@@ -20,5 +20,5 @@ rand_pcg = "0.9.0"
2020
criterion = "0.5.1"
2121

2222
[[bench]]
23-
name = "sudoku"
23+
name = "benches"
2424
harness = false

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ The Sudoku boards in `boards/mantere-koljonen` are from:
7979
> Computational Intelligence (WCCI 2008), 1-6 June, Hong Kong, China, pages
8080
> 4054-4061.
8181
82-
as made available [here](http://lipas.uwasa.fi/~timan/sudoku/).
82+
Made available [here](http://lipas.uwasa.fi/~timan/sudoku/).
8383

8484
Thanks much to the authors for collecting these.
8585

benches/benches.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#![warn(
2+
clippy::all,
3+
// clippy::restriction,
4+
clippy::pedantic,
5+
clippy::nursery,
6+
clippy::cargo
7+
)]
8+
9+
use criterion::{Criterion, black_box, criterion_group, criterion_main};
10+
use genetic_sudoku::genetics;
11+
use genetic_sudoku::genetics::{GAParams, MAX_POPULATION};
12+
use genetic_sudoku::sudoku::{Board, Row};
13+
use rand::prelude::StdRng;
14+
use rand::{Rng, SeedableRng, rng};
15+
use rand_pcg::Pcg64Mcg;
16+
17+
const BOARD_SIZE_4: usize = 4;
18+
19+
const BOARD_SIZE_9: usize = 9;
20+
21+
const GENERATION: usize = 0;
22+
23+
const POPULATION: usize = 100;
24+
25+
const SELECTION_RATE: f32 = 0.5;
26+
27+
const MUTATION_RATE: f32 = 0.05;
28+
29+
const BAD_BOARD: Board<4> = Board([
30+
Row([1, 2, 3, 4]),
31+
Row([1, 2, 3, 4]),
32+
Row([1, 2, 3, 4]),
33+
Row([1, 2, 3, 4]),
34+
]);
35+
36+
const EASY_4: Board<4> = Board([
37+
Row([1, 0, 0, 4]),
38+
Row([0, 4, 1, 2]),
39+
Row([2, 0, 4, 3]),
40+
Row([4, 3, 0, 0]),
41+
]);
42+
43+
fn bench_count_row_duplicates(c: &mut Criterion) {
44+
c.bench_function("count_row_duplicates", |b| {
45+
b.iter(|| black_box(BAD_BOARD).count_row_duplicates());
46+
});
47+
}
48+
49+
fn bench_count_box_duplicates(c: &mut Criterion) {
50+
c.bench_function("count_box_duplicates", |b| {
51+
b.iter(|| black_box(BAD_BOARD).count_box_duplicates());
52+
});
53+
}
54+
55+
fn bench_generate_initial_population(c: &mut Criterion) {
56+
let params = GAParams::new(POPULATION, SELECTION_RATE, MUTATION_RATE, None);
57+
58+
c.bench_function("generate_initial_population", |b| {
59+
b.iter(|| genetics::generate_initial_population::<BOARD_SIZE_9, MAX_POPULATION>(&params));
60+
});
61+
}
62+
63+
fn bench_run_simulation(c: &mut Criterion) {
64+
let params = GAParams::new(POPULATION, SELECTION_RATE, MUTATION_RATE, None);
65+
let population = genetics::generate_initial_population::<BOARD_SIZE_4, MAX_POPULATION>(&params);
66+
67+
c.bench_function("run_simulation", |b| {
68+
b.iter(|| {
69+
genetics::run_simulation::<BOARD_SIZE_4, MAX_POPULATION>(
70+
&params,
71+
GENERATION,
72+
&EASY_4,
73+
population.clone(),
74+
)
75+
});
76+
});
77+
}
78+
79+
fn bench_rng(c: &mut Criterion) {
80+
let mut rng = rng();
81+
82+
c.bench_function("rng", |b| {
83+
b.iter(|| black_box(&mut rng).random::<f32>());
84+
});
85+
}
86+
87+
fn bench_pcg64mcg(c: &mut Criterion) {
88+
let mut rng = Pcg64Mcg::from_rng(&mut StdRng::from_os_rng());
89+
90+
c.bench_function("Pcg64Mcg", |b| {
91+
b.iter(|| black_box(&mut rng).random::<f32>());
92+
});
93+
}
94+
95+
criterion_group!(
96+
benches,
97+
bench_count_row_duplicates,
98+
bench_count_box_duplicates,
99+
bench_generate_initial_population,
100+
bench_run_simulation,
101+
bench_rng,
102+
bench_pcg64mcg,
103+
);
104+
criterion_main!(benches);

benches/sudoku.rs

Lines changed: 0 additions & 57 deletions
This file was deleted.

src/genetics.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use super::errors::NoSolutionFound;
44
use super::sudoku::{Board, Row};
55
use arrayvec::ArrayVec;
6+
use rand::prelude::StdRng;
67
use rand::{Rng, SeedableRng, distr::Uniform};
78
use rand_pcg::Pcg64Mcg;
89
use rayon::iter::Zip;
@@ -77,8 +78,7 @@ pub fn generate_initial_population<const N: usize, const M: usize>(
7778
) -> Vec<Board<N>> {
7879
let max_digit = u8::try_from(N).expect("digit size exceeds 255");
7980
let values_range = Uniform::new_inclusive(1, max_digit).expect("invalid value range");
80-
let mut os_rng = rand::prelude::StdRng::from_os_rng();
81-
let mut rng = Pcg64Mcg::from_rng(&mut os_rng);
81+
let mut rng = Pcg64Mcg::from_rng(&mut StdRng::from_os_rng());
8282
let mut boards: Vec<Board<N>> = Vec::with_capacity(M);
8383

8484
for _ in 0..params.population {
@@ -220,8 +220,7 @@ fn make_children<const N: usize, const M: usize>(
220220
(0..params.num_children_per_parent_pairs)
221221
.into_par_iter()
222222
.map(|_| {
223-
let mut x = rand::prelude::StdRng::from_os_rng();
224-
let mut rng = Pcg64Mcg::from_rng(&mut x);
223+
let mut rng = Pcg64Mcg::from_rng(&mut StdRng::from_os_rng());
225224
let mut child: ArrayVec<Row<N>, N> = ArrayVec::new_const();
226225

227226
for i in 0..N {

src/main.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ use std::time::{Duration, Instant};
1313
// The board size for puzzles. Change this for larger or smaller boards.
1414
const BOARD_SIZE: usize = 9;
1515

16-
const MAX_GENERATIONS: usize = 100_000;
17-
1816
const TIMEOUT: u64 = 600;
1917

2018
#[derive(Parser, Debug)]
@@ -97,7 +95,7 @@ fn main() -> Result<(), Box<dyn Error>> {
9795
Err(no_solution_found) => {
9896
generation += 1;
9997

100-
if generation >= MAX_GENERATIONS || Instant::now().ge(&timeout) {
98+
if Instant::now().ge(&timeout) {
10199
println!("Generation: {generation} | Duration: {:?}", now.elapsed());
102100

103101
return Err(no_solution_found.into());

src/sudoku.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
use arrayvec::ArrayVec;
44
use std::fmt;
55
use std::fmt::{Debug, Display, Formatter};
6+
use std::fs;
7+
use std::io::{Error, ErrorKind};
8+
use std::path::Path;
69

710
#[derive(Debug, Default)]
811
struct Scorer {
@@ -198,16 +201,12 @@ impl<const N: usize> Board<N> {
198201
///
199202
/// Fails if file is nonexistent, unreadable, or of the wrong size.
200203
#[inline]
201-
pub fn read<P: AsRef<std::path::Path>>(path: P) -> Result<Self, std::io::Error> {
202-
let board = std::fs::read_to_string(path)?;
203-
let format_error =
204-
|| std::io::Error::new(std::io::ErrorKind::InvalidData, "malformed sudoku board");
204+
pub fn read<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
205+
let board = fs::read_to_string(path)?;
206+
let format_error = || Error::new(ErrorKind::InvalidData, "malformed sudoku board");
205207
let dim = board.lines().next().ok_or_else(format_error)?.len();
206208
if dim != N {
207-
return Err(std::io::Error::new(
208-
std::io::ErrorKind::InvalidData,
209-
"wrong board size",
210-
));
209+
return Err(Error::new(ErrorKind::InvalidData, "wrong board size"));
211210
}
212211
let mut board_array: [Row<N>; N] = [<Row<N>>::default(); N];
213212
let mut chars = board.chars();

0 commit comments

Comments
 (0)