From d4700d85a6c77224483d2ccae451e3b5b78edcf2 Mon Sep 17 00:00:00 2001 From: Gunter Schmidt Date: Sun, 15 Jun 2025 03:04:45 +0200 Subject: [PATCH] Code reorganization without functional changes. Consolidated Node, moved the file operation out of the decider (passing TM instead), split in library and executable and added a benchmark. --- .../Cargo.toml | 18 +- .../decider_halting_segment/Cargo.toml | 15 ++ .../benches/benchmarks-criterion.rs | 45 ++++ .../src/lib.rs} | 204 ++++-------------- .../src/node.rs} | 140 +++++++++++- .../{ => decider_halting_segment}/src/tm.rs | 8 +- .../src/utils.rs | 0 .../dhs_app/Cargo.toml | 14 ++ .../dhs_app/src/main.rs | 82 +++++++ .../src/display_nodes.rs | 83 ------- 10 files changed, 347 insertions(+), 262 deletions(-) create mode 100644 decider-halting-segment-reproduction/decider_halting_segment/Cargo.toml create mode 100644 decider-halting-segment-reproduction/decider_halting_segment/benches/benchmarks-criterion.rs rename decider-halting-segment-reproduction/{src/main.rs => decider_halting_segment/src/lib.rs} (67%) rename decider-halting-segment-reproduction/{src/neighbours.rs => decider_halting_segment/src/node.rs} (59%) rename decider-halting-segment-reproduction/{ => decider_halting_segment}/src/tm.rs (97%) rename decider-halting-segment-reproduction/{ => decider_halting_segment}/src/utils.rs (100%) create mode 100644 decider-halting-segment-reproduction/dhs_app/Cargo.toml create mode 100644 decider-halting-segment-reproduction/dhs_app/src/main.rs delete mode 100644 decider-halting-segment-reproduction/src/display_nodes.rs diff --git a/decider-halting-segment-reproduction/Cargo.toml b/decider-halting-segment-reproduction/Cargo.toml index 5e9ac07..fe214e4 100644 --- a/decider-halting-segment-reproduction/Cargo.toml +++ b/decider-halting-segment-reproduction/Cargo.toml @@ -1,14 +1,4 @@ -[package] -edition = "2018" -name = "halting-segment-reproduction" -version = "0.1.0" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -indicatif = {version = "*", features = ["rayon"]} -rayon = "1.5" -rand = "*" -indexmap = "1.9" -jemallocator = "0.5" -argh = "0.1" +[workspace] +resolver = "2" +members = ["dhs_app", "decider_halting_segment"] +default-members = ["dhs_app"] diff --git a/decider-halting-segment-reproduction/decider_halting_segment/Cargo.toml b/decider-halting-segment-reproduction/decider_halting_segment/Cargo.toml new file mode 100644 index 0000000..18bded9 --- /dev/null +++ b/decider-halting-segment-reproduction/decider_halting_segment/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "decider_halting_segment_reproduction" +version = "0.1.0" +edition = "2021" + +[dependencies] +indexmap = "1.9" + +# [dev-dependencies] +criterion = { version = "0.5", features = ["html_reports"] } + +[[bench]] +name = "bench_bb_challenge" +path = "benches/benchmarks-criterion.rs" +harness = false diff --git a/decider-halting-segment-reproduction/decider_halting_segment/benches/benchmarks-criterion.rs b/decider-halting-segment-reproduction/decider_halting_segment/benches/benchmarks-criterion.rs new file mode 100644 index 0000000..6a54acb --- /dev/null +++ b/decider-halting-segment-reproduction/decider_halting_segment/benches/benchmarks-criterion.rs @@ -0,0 +1,45 @@ +#![allow(dead_code)] +#![allow(non_snake_case)] + +use criterion::{criterion_group, criterion_main, Criterion}; +use decider_halting_segment_reproduction::{ + tm::TM, Iijil_strategy, Iijil_strategy_updated, PATH_TO_BBCHALLENGE_DB_TEST, +}; +use std::time::Duration; + +const WARM_UP_TIME_MS: u64 = 500; +const MEASUREMENT_TIME_MS: u64 = 2000; + +fn benchmark_Iijil_strategy(c: &mut Criterion) { + // let tm = TM::from_bbchallenge_id(23367211, PATH_TO_BBCHALLENGE_DB_TEST); + + let mut group = c.benchmark_group("Bench Tape Type"); + + group.warm_up_time(Duration::from_millis(WARM_UP_TIME_MS)); + group.measurement_time(Duration::from_millis(MEASUREMENT_TIME_MS)); + // group.sample_size(50); + + group.bench_function("Iijil_strategy_23367211", |b| { + b.iter(|| Iijil_strategy_23367211()) + }); + + group.bench_function("Iijil_strategy_updated_23367211", |b| { + b.iter(|| Iijil_strategy_updated_23367211()) + }); + + group.finish(); +} + +fn Iijil_strategy_23367211() { + let turing_machine = TM::from_bbchallenge_id(23367211, PATH_TO_BBCHALLENGE_DB_TEST).unwrap(); + assert!(Iijil_strategy(turing_machine, 200000, false)) +} + +fn Iijil_strategy_updated_23367211() { + // Segment size 15 = 2*7+1 + let turing_machine = TM::from_bbchallenge_id(23367211, PATH_TO_BBCHALLENGE_DB_TEST).unwrap(); + assert!(Iijil_strategy_updated(turing_machine, 7, false)) +} + +criterion_group!(benches, benchmark_Iijil_strategy,); +criterion_main!(benches); diff --git a/decider-halting-segment-reproduction/src/main.rs b/decider-halting-segment-reproduction/decider_halting_segment/src/lib.rs similarity index 67% rename from decider-halting-segment-reproduction/src/main.rs rename to decider-halting-segment-reproduction/decider_halting_segment/src/lib.rs index 3ee06a6..31d2734 100644 --- a/decider-halting-segment-reproduction/src/main.rs +++ b/decider-halting-segment-reproduction/decider_halting_segment/src/lib.rs @@ -1,75 +1,19 @@ -use std::{fmt, fs::File, io::Read}; - -use std::io::prelude::*; +// pub mod display_nodes; +pub mod node; +pub mod tm; +pub mod utils; use indexmap::IndexSet; -use rand::{distributions::Alphanumeric, Rng}; - -use indicatif::{ParallelProgressIterator, ProgressStyle}; - -use rayon::prelude::*; -use std::convert::TryInto; - -mod display_nodes; -mod neighbours; -mod tm; -mod utils; - -use tm::{HaltOrGoto, HeadMove, TM}; -use utils::u8_to_bool; - -#[global_allocator] -static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; - -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -enum SegmentCell { - Unallocated, - Bit(bool), -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -enum OutsideSegmentOrState { - OutsideSegment, - State(u8), -} - -#[derive(Clone, PartialEq, Eq, Hash)] -struct SegmentCells(pub Vec); - -impl SegmentCells { - fn are_there_no_ones(&self) -> bool { - !self - .0 - .iter() - .any(|cell| matches!(cell, SegmentCell::Bit(true))) - } -} - -#[derive(Clone, PartialEq, Eq, Hash)] -struct Node { - state: OutsideSegmentOrState, - segment: SegmentCells, - pos_in_segment: usize, -} -impl Node { - fn is_fatal(&self) -> bool { - /* Fatal nodes are nodes whose segment contain no 1s and: - - head is outside segment - - Or, state is A - Detecting these nodes is important because when the decider meets one, we know - that we cannot conclude that the machine does not halt. - */ - match self.state { - OutsideSegmentOrState::OutsideSegment | OutsideSegmentOrState::State(0) => { - self.segment.are_there_no_ones() - } - _ => false, - } - } -} +use crate::{ + node::{Node, NodeLimit, OutsideSegmentOrState, SegmentCell, SegmentCells}, + tm::{HaltOrGoto, TM}, + utils::u8_to_bool, +}; -struct Nodes(pub Vec); +// #[cfg(test)] +pub const PATH_TO_BBCHALLENGE_DB_TEST: &str = + "../../all_5_states_undecided_machines_with_global_header"; #[derive(Debug, PartialEq, Eq)] enum HaltingSegmentResult { @@ -99,11 +43,6 @@ fn get_initial_nodes(tm: &TM, segment_size: u8, initial_pos_in_segment: usize) - to_return } -enum NodeLimit { - NoLimit, - NodeLimit(usize), -} - fn halting_segment_decider( tm: &TM, segment_size: u8, @@ -137,10 +76,8 @@ fn halting_segment_decider( HaltingSegmentResult::MachineDoesNotHalt(idx_seen) } -const PATH_TO_BBCHALLENGE_DB: &str = "../all_5_states_undecided_machines_with_global_header"; -const PATH_TO_UNDECIDED_INDEX: &str = "../bb5_undecided_index"; - -fn Iijil_strategy(machine_id: u32, node_limit: usize, print_run_info: bool) -> bool { +#[allow(non_snake_case)] +pub fn Iijil_strategy(turing_machine: TM, node_limit: usize, print_run_info: bool) -> bool { /* Implements @Iijil's strategy for running the backward halting segment decider: - The decider is run with all odd segment length until success or cumulative node limit is reached - Initial position in the segment is middle of it @@ -150,10 +87,9 @@ fn Iijil_strategy(machine_id: u32, node_limit: usize, print_run_info: bool) -> b let mut distance_to_segment_end: u8 = 1; let mut total_nodes_consumed = 0; - let tm = TM::from_bbchallenge_id(machine_id, PATH_TO_BBCHALLENGE_DB).unwrap(); if print_run_info { - println!("Machine ID: {}", machine_id); - println!("{}", tm); + println!("Machine ID: {}", turing_machine.machine_id); + println!("{}", turing_machine); } while total_nodes_consumed < node_limit { let segment_size = 2 * distance_to_segment_end + 1; @@ -164,7 +100,7 @@ fn Iijil_strategy(machine_id: u32, node_limit: usize, print_run_info: bool) -> b } let result = halting_segment_decider( - &tm, + &turing_machine, segment_size, initial_pos_in_segment, NodeLimit::NodeLimit(node_limit), @@ -175,7 +111,7 @@ fn Iijil_strategy(machine_id: u32, node_limit: usize, print_run_info: bool) -> b HaltingSegmentResult::MachineDoesNotHalt(nb_nodes) => { if print_run_info { println!( - "Machine {} proved nonhalting with segment size {} and initial position {} after expanding {} nodes, and cumulatively {} nodes in search", machine_id, + "Machine {} proved nonhalting with segment size {} and initial position {} after expanding {} nodes, and cumulatively {} nodes in search", turing_machine. machine_id, segment_size, initial_pos_in_segment, nb_nodes, nb_nodes+total_nodes_consumed ); } @@ -204,8 +140,9 @@ fn Iijil_strategy(machine_id: u32, node_limit: usize, print_run_info: bool) -> b false } -fn Iijil_strategy_updated( - machine_id: u32, +#[allow(non_snake_case)] +pub fn Iijil_strategy_updated( + turing_machine: TM, distance_to_end_limit: u8, print_run_info: bool, ) -> bool { @@ -219,10 +156,10 @@ fn Iijil_strategy_updated( let mut distance_to_segment_end: u8 = 1; let mut total_nodes_consumed = 0; - let tm = TM::from_bbchallenge_id(machine_id, PATH_TO_BBCHALLENGE_DB).unwrap(); + // let turing_machine = TM::from_bbchallenge_id(machine_id, path_to_bb_challenge_db).unwrap(); if print_run_info { - println!("Machine ID: {}", machine_id); - println!("{}", tm); + println!("Machine ID: {}", turing_machine.machine_id); + println!("{}", turing_machine); } while distance_to_segment_end <= distance_to_end_limit { let segment_size = 2 * distance_to_segment_end + 1; @@ -233,7 +170,7 @@ fn Iijil_strategy_updated( } let result = halting_segment_decider( - &tm, + &turing_machine, segment_size, initial_pos_in_segment, NodeLimit::NoLimit, @@ -244,7 +181,7 @@ fn Iijil_strategy_updated( HaltingSegmentResult::MachineDoesNotHalt(nb_nodes) => { if print_run_info { println!( - "Machine {} proved nonhalting with segment size {} and initial position {} after expanding {} nodes, and cumulatively {} nodes in search", machine_id, + "Machine {} proved nonhalting with segment size {} and initial position {} after expanding {} nodes, and cumulatively {} nodes in search", turing_machine. machine_id, segment_size, initial_pos_in_segment, nb_nodes, nb_nodes+total_nodes_consumed ); } @@ -273,71 +210,8 @@ fn Iijil_strategy_updated( false } -use argh::FromArgs; - -fn default_distance_to_end_limit() -> u8 { - 5 -} - -#[derive(FromArgs)] -/// Halting segment deciders using @Iijil's updated search strategy. -struct SearchArgs { - /// maximum size from center of segment to extremity, i.e. total size of segment is 2x+1 - #[argh(option, short = 'n', default = "default_distance_to_end_limit()")] - distance_to_end_limit: u8, -} - -fn main() { - let searchArgs: SearchArgs = argh::from_env(); - - let mut undecided_index_file = File::open(PATH_TO_UNDECIDED_INDEX).unwrap(); - let mut raw_data: Vec = Vec::new(); - - undecided_index_file.read_to_end(&mut raw_data).unwrap(); - - let undecided_ids: Vec = raw_data - .chunks_exact(4) - .map(|s| s.try_into().unwrap()) - .map(u32::from_be_bytes) - .collect(); - - let style = ProgressStyle::with_template( - "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}", - ) - .unwrap() - .progress_chars("##-"); - - let mut decided_ids: Vec<&u32> = undecided_ids - .par_iter() - .progress_with_style(style) - .filter(|&id| Iijil_strategy_updated(*id, searchArgs.distance_to_end_limit, false)) - .collect(); - - decided_ids.sort(); - - println!( - "{} machines decided by halting segment, starting from center of odd-size segments up to size {} (using @Iijil's updated strategy)", - decided_ids.len(), 2*searchArgs.distance_to_end_limit+1 - ); - - let mut random_id: String = rand::thread_rng() - .sample_iter(&Alphanumeric) - .take(12) - .map(char::from) - .collect(); - random_id = random_id.to_ascii_lowercase(); - - let d = searchArgs.distance_to_end_limit; - let output_file = - format!("output/halting-segment-reproduction-run-{random_id}-max-distance-to-end-{d}"); - - let mut file = File::create(output_file).unwrap(); - for id in decided_ids { - file.write_all(&u32::to_be_bytes(*id)).unwrap(); - } -} - #[cfg(test)] +#[allow(non_snake_case)] mod tests { use super::*; @@ -346,7 +220,8 @@ mod tests { // http://turbotm.de/~heiner/BB/TM4-proof.txt // Chaotic Machine [Marxen & Buntrock, 1990] let chaotic_machine_id = 76708232; - let tm: TM = TM::from_bbchallenge_id(chaotic_machine_id, PATH_TO_BBCHALLENGE_DB).unwrap(); + let tm: TM = + TM::from_bbchallenge_id(chaotic_machine_id, PATH_TO_BBCHALLENGE_DB_TEST).unwrap(); assert_eq!( halting_segment_decider(&tm, 5, 2, NodeLimit::NodeLimit(1000), false), // 7 nodes expanded, cross checked with @Iijil @@ -358,7 +233,8 @@ mod tests { fn complex_counter() { // Complex Counter [Marxen & Buntrock, 1990] let chaotic_machine_id = 10936909; - let tm: TM = TM::from_bbchallenge_id(chaotic_machine_id, PATH_TO_BBCHALLENGE_DB).unwrap(); + let tm: TM = + TM::from_bbchallenge_id(chaotic_machine_id, PATH_TO_BBCHALLENGE_DB_TEST).unwrap(); assert_eq!( halting_segment_decider(&tm, 7, 3, NodeLimit::NodeLimit(1000), false), @@ -371,7 +247,8 @@ mod tests { fn machine_108115() { // bbchallenge machine 108115 let chaotic_machine_id = 108115; - let tm: TM = TM::from_bbchallenge_id(chaotic_machine_id, PATH_TO_BBCHALLENGE_DB).unwrap(); + let tm: TM = + TM::from_bbchallenge_id(chaotic_machine_id, PATH_TO_BBCHALLENGE_DB_TEST).unwrap(); assert_eq!( halting_segment_decider(&tm, 3, 1, NodeLimit::NodeLimit(1000), false), @@ -382,13 +259,17 @@ mod tests { #[test] fn Iijil_strategy_23367211() { - assert!(Iijil_strategy(23367211, 200000, true)) + let turing_machine = + TM::from_bbchallenge_id(23367211, PATH_TO_BBCHALLENGE_DB_TEST).unwrap(); + assert!(Iijil_strategy(turing_machine, 200000, true)) } #[test] fn Iijil_strategy_updated_23367211() { + let turing_machine = + TM::from_bbchallenge_id(23367211, PATH_TO_BBCHALLENGE_DB_TEST).unwrap(); // Segment size 15 = 2*7+1 - assert!(Iijil_strategy_updated(23367211, 7, true)) + assert!(Iijil_strategy_updated(turing_machine, 7, true)) } #[test] @@ -420,13 +301,14 @@ mod tests { 29798909, ]; - for id in &missing { + for &id in &missing { let mut node_limit = 20000; - let mut r = Iijil_strategy(*id, node_limit, false); + let turing_machine = TM::from_bbchallenge_id(id, PATH_TO_BBCHALLENGE_DB_TEST).unwrap(); + let mut r = Iijil_strategy(turing_machine.clone(), node_limit, false); while !r && node_limit < 200000000 { node_limit *= 10; println!("Machine {} up {}", id, node_limit); - r = Iijil_strategy(*id, node_limit, false); + r = Iijil_strategy(turing_machine.clone(), node_limit, false); } assert!(r); } diff --git a/decider-halting-segment-reproduction/src/neighbours.rs b/decider-halting-segment-reproduction/decider_halting_segment/src/node.rs similarity index 59% rename from decider-halting-segment-reproduction/src/neighbours.rs rename to decider-halting-segment-reproduction/decider_halting_segment/src/node.rs index bcbf91d..6ca1a98 100644 --- a/decider-halting-segment-reproduction/src/neighbours.rs +++ b/decider-halting-segment-reproduction/decider_halting_segment/src/node.rs @@ -1,6 +1,59 @@ -use crate::*; +use std::fmt; + +use crate::{tm::HeadMove, *}; + +pub(crate) enum NodeLimit { + NoLimit, + NodeLimit(usize), +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub enum OutsideSegmentOrState { + OutsideSegment, + State(u8), +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub enum SegmentCell { + Unallocated, + Bit(bool), +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub(crate) struct SegmentCells(pub Vec); + +impl SegmentCells { + fn are_there_no_ones(&self) -> bool { + !self + .0 + .iter() + .any(|cell| matches!(cell, SegmentCell::Bit(true))) + } +} + +#[derive(Clone, PartialEq, Eq, Hash)] +pub(crate) struct Node { + pub(crate) state: OutsideSegmentOrState, + pub(crate) segment: SegmentCells, + pub(crate) pos_in_segment: usize, +} impl Node { + pub(crate) fn is_fatal(&self) -> bool { + /* Fatal nodes are nodes whose segment contain no 1s and: + - head is outside segment + - Or, state is A + Detecting these nodes is important because when the decider meets one, we know + that we cannot conclude that the machine does not halt. + */ + match self.state { + OutsideSegmentOrState::OutsideSegment | OutsideSegmentOrState::State(0) => { + self.segment.are_there_no_ones() + } + _ => false, + } + } + pub fn get_neighbours(&self, tm: &TM) -> Vec { /* Returns the halting segment neighbours of the node: @@ -145,3 +198,88 @@ impl Node { to_return } } + +impl fmt::Display for Node { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /* + State: E ; _ . .[0]. . _ ; + */ + let state_char: char = match self.state { + OutsideSegmentOrState::OutsideSegment => '*', + OutsideSegmentOrState::State(state) => (b'A' + state) as char, + }; + + write!(f, "State: {} ; ", state_char)?; + + let is_outside = matches!(self.state, OutsideSegmentOrState::OutsideSegment); + + if is_outside && self.pos_in_segment == 0 { + write!(f, "[_]")?; + } else { + write!(f, " _")?; + } + + for i in 0..self.segment.0.len() { + if i == 0 && (i != self.pos_in_segment && !is_outside) { + write!(f, " ")?; + } + + let mut space_after = true; + match self.segment.0[i] { + SegmentCell::Unallocated => write!(f, ".")?, + SegmentCell::Bit(bit) => { + if i != self.pos_in_segment || is_outside { + write!(f, "{}", bit as u8)?; + } else { + write!(f, "[{}]", bit as u8)?; + space_after = false; + } + } + } + if space_after && (i + 1 != self.pos_in_segment || is_outside) { + write!(f, " ")?; + } + } + + if is_outside && self.pos_in_segment + 1 == self.segment.0.len() { + write!(f, "[_]")?; + } else { + write!(f, " _")?; + } + + write!(f, "") + } +} + +// pub(crate) struct Nodes(pub Vec); +// +// impl fmt::Display for Nodes { +// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +// for (i, node) in self.0.iter().enumerate() { +// writeln!(f, "{}: {}", i, node)?; +// } +// write!(f, "") +// } +// } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn machine_324_trace() { + let chaotic_machine_id = 324; + let tm: TM = TM::from_bbchallenge_id(chaotic_machine_id, PATH_TO_BBCHALLENGE_DB_TEST).unwrap(); + + halting_segment_decider(&tm, 5, 2, NodeLimit::NodeLimit(1000), true); + } + + #[test] + fn machine_chaotic_trace() { + // Chaotic Machine [Marxen & Buntrock, 1990] + let chaotic_machine_id = 76708232; + let tm: TM = TM::from_bbchallenge_id(chaotic_machine_id, PATH_TO_BBCHALLENGE_DB_TEST).unwrap(); + + halting_segment_decider(&tm, 5, 2, NodeLimit::NodeLimit(1000), true); + } +} diff --git a/decider-halting-segment-reproduction/src/tm.rs b/decider-halting-segment-reproduction/decider_halting_segment/src/tm.rs similarity index 97% rename from decider-halting-segment-reproduction/src/tm.rs rename to decider-halting-segment-reproduction/decider_halting_segment/src/tm.rs index 9c9ebea..42890ee 100644 --- a/decider-halting-segment-reproduction/src/tm.rs +++ b/decider-halting-segment-reproduction/decider_halting_segment/src/tm.rs @@ -54,6 +54,7 @@ impl fmt::Display for Transition { #[derive(Clone)] pub struct TM { + pub machine_id: u32, pub n_states: u8, pub n_symbols: u8, pub transitions: Vec>, @@ -119,6 +120,7 @@ impl TM { } Ok(TM { + machine_id, n_states: 5, n_symbols: 2, transitions, @@ -128,9 +130,9 @@ impl TM { #[cfg(test)] mod tests { - use super::*; + use crate::PATH_TO_BBCHALLENGE_DB_TEST; - const PATH_TO_BBCHALLENGE_DB: &str = "../all_5_states_undecided_machines_with_global_header"; + use super::*; #[test] fn bbchallenge_format() { @@ -142,7 +144,7 @@ mod tests { ]; for (id, format) in ids_and_format { - let computed = TM::from_bbchallenge_id(id, PATH_TO_BBCHALLENGE_DB) + let computed = TM::from_bbchallenge_id(id, PATH_TO_BBCHALLENGE_DB_TEST) .unwrap() .to_string(); println!("{}", computed); diff --git a/decider-halting-segment-reproduction/src/utils.rs b/decider-halting-segment-reproduction/decider_halting_segment/src/utils.rs similarity index 100% rename from decider-halting-segment-reproduction/src/utils.rs rename to decider-halting-segment-reproduction/decider_halting_segment/src/utils.rs diff --git a/decider-halting-segment-reproduction/dhs_app/Cargo.toml b/decider-halting-segment-reproduction/dhs_app/Cargo.toml new file mode 100644 index 0000000..efda3ac --- /dev/null +++ b/decider-halting-segment-reproduction/dhs_app/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "decider_halting_segment_app" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +argh = "0.1" +indicatif = { version = "*", features = ["rayon"] } +rand = "0.8" +rayon = "1.5" +jemallocator = "0.5" +decider_halting_segment_reproduction = { path = "../decider_halting_segment" } diff --git a/decider-halting-segment-reproduction/dhs_app/src/main.rs b/decider-halting-segment-reproduction/dhs_app/src/main.rs new file mode 100644 index 0000000..96b9d8e --- /dev/null +++ b/decider-halting-segment-reproduction/dhs_app/src/main.rs @@ -0,0 +1,82 @@ +use argh::FromArgs; +use decider_halting_segment_reproduction::{tm::TM, Iijil_strategy_updated}; +use indicatif::{ParallelProgressIterator, ProgressStyle}; +use rand::{distributions::Alphanumeric, Rng}; +use rayon::prelude::*; +use std::{ + fs::File, + io::{Read, Write}, +}; + +#[global_allocator] +static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; + +const PATH_TO_BBCHALLENGE_DB: &str = "../all_5_states_undecided_machines_with_global_header"; +// "../../../../busy_beaver_challenge_extras/res/all_5_states_undecided_machines_with_global_header"; +/// https://github.com/bbchallenge/bbchallenge-undecided-index +const PATH_TO_UNDECIDED_INDEX: &str = "../bb5_undecided_index"; + +fn default_distance_to_end_limit() -> u8 { + 5 +} + +#[derive(FromArgs)] +/// Halting segment deciders using @Iijil's updated search strategy. +struct SearchArgs { + /// maximum size from center of segment to extremity, i.e. total size of segment is 2x+1 + #[argh(option, short = 'n', default = "default_distance_to_end_limit()")] + distance_to_end_limit: u8, +} + +fn main() { + let search_args: SearchArgs = argh::from_env(); + + let mut undecided_index_file = File::open(PATH_TO_UNDECIDED_INDEX).unwrap(); + let mut raw_data: Vec = Vec::new(); + + undecided_index_file.read_to_end(&mut raw_data).unwrap(); + + let undecided_ids: Vec = raw_data + .chunks_exact(4) + .map(|s| s.try_into().unwrap()) + .map(u32::from_be_bytes) + .collect(); + + let style = ProgressStyle::with_template( + "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}", + ) + .unwrap() + .progress_chars("##-"); + + let mut decided_ids: Vec<&u32> = undecided_ids + .par_iter() + .progress_with_style(style) + .filter(|&id| { + let turing_machine = TM::from_bbchallenge_id(*id, PATH_TO_BBCHALLENGE_DB).unwrap(); + Iijil_strategy_updated(turing_machine, search_args.distance_to_end_limit, false) + }) + .collect(); + + decided_ids.sort(); + + println!( + "{} machines decided by halting segment, starting from center of odd-size segments up to size {} (using @Iijil's updated strategy)", + decided_ids.len(), 2*search_args.distance_to_end_limit+1 + ); + + let mut random_id: String = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(12) + .map(char::from) + .collect(); + random_id = random_id.to_ascii_lowercase(); + + let d = search_args.distance_to_end_limit; + let output_file = + format!("output/halting-segment-reproduction-run-{random_id}-max-distance-to-end-{d}"); + + let mut file = File::create(output_file).unwrap(); + for id in decided_ids { + file.write_all(&u32::to_be_bytes(*id)).unwrap(); + } +} diff --git a/decider-halting-segment-reproduction/src/display_nodes.rs b/decider-halting-segment-reproduction/src/display_nodes.rs deleted file mode 100644 index 017f0b9..0000000 --- a/decider-halting-segment-reproduction/src/display_nodes.rs +++ /dev/null @@ -1,83 +0,0 @@ -use crate::*; - -impl fmt::Display for Node { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - /* - State: E ; _ . .[0]. . _ ; - */ - let state_char: char = match self.state { - OutsideSegmentOrState::OutsideSegment => '*', - OutsideSegmentOrState::State(state) => (b'A' + state) as char, - }; - - write!(f, "State: {} ; ", state_char)?; - - let is_outside = matches!(self.state, OutsideSegmentOrState::OutsideSegment); - - if is_outside && self.pos_in_segment == 0 { - write!(f, "[_]")?; - } else { - write!(f, " _")?; - } - - for i in 0..self.segment.0.len() { - if i == 0 && (i != self.pos_in_segment && !is_outside) { - write!(f, " ")?; - } - - let mut space_after = true; - match self.segment.0[i] { - SegmentCell::Unallocated => write!(f, ".")?, - SegmentCell::Bit(bit) => { - if i != self.pos_in_segment || is_outside { - write!(f, "{}", bit as u8)?; - } else { - write!(f, "[{}]", bit as u8)?; - space_after = false; - } - } - } - if space_after && (i + 1 != self.pos_in_segment || is_outside) { - write!(f, " ")?; - } - } - - if is_outside && self.pos_in_segment + 1 == self.segment.0.len() { - write!(f, "[_]")?; - } else { - write!(f, " _")?; - } - - write!(f, "") - } -} - -impl fmt::Display for Nodes { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - for (i, node) in self.0.iter().enumerate() { - writeln!(f, "{}: {}", i, node)?; - } - write!(f, "") - } -} - -mod tests { - use super::*; - - #[test] - fn machine_324_trace() { - let chaotic_machine_id = 324; - let tm: TM = TM::from_bbchallenge_id(chaotic_machine_id, PATH_TO_BBCHALLENGE_DB).unwrap(); - - halting_segment_decider(&tm, 5, 2, NodeLimit::NodeLimit(1000), true); - } - - #[test] - fn machine_chaotic_trace() { - // Chaotic Machine [Marxen & Buntrock, 1990] - let chaotic_machine_id = 76708232; - let tm: TM = TM::from_bbchallenge_id(chaotic_machine_id, PATH_TO_BBCHALLENGE_DB).unwrap(); - - halting_segment_decider(&tm, 5, 2, NodeLimit::NodeLimit(1000), true); - } -}