TuringMachine

Trait TuringMachine 

Source
pub trait TuringMachine<S: Symbol> {
    // Required methods
    fn execute_once(
        &self,
        conf: Configuration<S>,
    ) -> Result<Configuration<S>, String>;
    fn execute_until(
        &self,
        conf: Configuration<S>,
        until: impl Fn(&Configuration<S>) -> bool,
    ) -> Result<Configuration<S>, String>;

    // Provided methods
    fn execute(
        &self,
        conf: Configuration<S>,
    ) -> Result<Configuration<S>, String> { ... }
    fn translate_std(&self, tape: Tape<S>) -> Result<Tape<S>, String> { ... }
    fn translate_nrm(&self, tape: Tape<S>) -> Result<Tape<S>, String> { ... }
}
Expand description

Provides ability to execute crate::state::Configurations and translate crate::state::Tapes.

Most of the methods can be implement through the TuringMachine::execute_once and TuringMachine::execute_until methods.

Most important trait.

§Examples

extern crate turing_machine_rs;

use turing_machine_rs::instruction::{Move, State};
use turing_machine_rs::machines::Classic;
use turing_machine_rs::program::{Extend, Program};
use turing_machine_rs::state::Tape;
use turing_machine_rs::TuringMachine;

fn main() -> Result<(), String> {
   let alphabet = vec!['t', 'e', 's', 'n', 'i', 'c', 'e', '_'];
   let mut program = Program::new(alphabet, State(4));
    // Trait for more comfortable coding
    program.extend([
        // Instruction consists of Head and Tail parts
        // Head state, Head symbol, Tail state, Tail symbol, Tail Move
        (1, 't', 2, 'n', Move::Right),
        (2, 'e', 3, 'i', Move::Right),
        (3, 's', 4, 'c', Move::Right),
        (4, 't', 0, 'e', Move::None),
        // Revers
        (1, 'n', 2, 't', Move::Right),
        (2, 'i', 3, 'e', Move::Right),
        (3, 'c', 4, 's', Move::Right),
        (4, 'e', 0, 't', Move::None),
    ])?;
    let machine = Classic::new(program, '_')?;

    let test = Tape::from("test");
    let nice = machine.translate_nrm(test.clone())?;
    println!(
        "{} {}!",
        String::from_iter(nice.as_vec()),
        String::from_iter(test.as_vec())
    );
    Ok(())
}

Required Methods§

Source

fn execute_once( &self, conf: Configuration<S>, ) -> Result<Configuration<S>, String>

A Turing machine must have the ability to execute crate::program::Program and change the Configuration once. This is important for machines, and its realization can vary depending on machine type.

Source

fn execute_until( &self, conf: Configuration<S>, until: impl Fn(&Configuration<S>) -> bool, ) -> Result<Configuration<S>, String>

Executes program untill stop predicate equals to false and returns a mutated Configuration.

§Examples
use turing_machine_rs::instruction::{Move, State};
use turing_machine_rs::machines::Classic;
use turing_machine_rs::program::{Extend, Program};
use turing_machine_rs::state::{Configuration, Tape};
use turing_machine_rs::TuringMachine;

fn main() -> Result<(), String> {
    let mut program = Program::new(vec!['0', '1'], State(3));
    program.extend([
        (1, '0', 2, '0', Move::Right),
        (1, '1', 1, '1', Move::Left),
        (2, '0', 3, '1', Move::Left),
        (2, '1', 2, '1', Move::Right),
        (3, '0', 0, '0', Move::None),
        (3, '1', 3, '0', Move::Left),
    ])?;
    let machine = Classic::new(program, '0')?;

    let conf = Configuration::new_std(Tape::from("010"))?;
    let result = machine.execute_until(conf, |conf| conf.state == State(3))?;

    let expected = Configuration::new(Tape::from("0101"), 2, State(3))?;
    assert_eq!(expected, result);

    Ok(())
}

Provided Methods§

Source

fn execute(&self, conf: Configuration<S>) -> Result<Configuration<S>, String>

Executes the crate::program::Program and returns a mutated Configuration using the TuringMachine::execute_until method with the conf.state == 0 predicate. This is the most commonly used method for crate::program::Program execution.

Examples found in repository?
examples/hyper_machine.rs (line 84)
11fn main() -> Result<(), String> {
12    use nrm_machines::*;
13
14    let stand = new_stand_machine();
15    let zerofy = new_zerofy_machine();
16    let l_shift = new_left_shift_machine();
17    let r_shift = new_right_shift_machine();
18    let trans = new_trans_machine();
19
20    let mut program = Program::new(
21        vec![
22            stand.clone(),
23            zerofy.clone(),
24            l_shift.clone(),
25            r_shift.clone(),
26            trans.clone(),
27        ],
28        State(9),
29    );
30    // This is simplest implementation of `change choose second to choose third` machine
31    program.extend([
32        // Find l_shift
33        (1, r_shift.clone(), 1, r_shift.clone(), Move::Right),
34        (1, trans.clone(), 1, trans.clone(), Move::Right),
35        (1, zerofy.clone(), 1, zerofy.clone(), Move::Right),
36        (1, l_shift.clone(), 2, stand.clone(), Move::Left),
37        // Clear until r_shift
38        (2, zerofy.clone(), 2, stand.clone(), Move::Left),
39        (2, trans.clone(), 2, stand.clone(), Move::Left),
40        (2, r_shift.clone(), 3, r_shift.clone(), Move::Right),
41        //
42        // Set second r_shift
43        (3, stand.clone(), 4, r_shift.clone(), Move::Right),
44        // Set first trans
45        (4, stand.clone(), 5, trans.clone(), Move::Right),
46        // Set first zerofy
47        (5, stand.clone(), 6, zerofy.clone(), Move::Right),
48        // Set first l_shift
49        (6, stand.clone(), 7, l_shift.clone(), Move::Right),
50        // Set second trans
51        (7, stand.clone(), 8, trans.clone(), Move::Right),
52        // Set second zerofy
53        (8, stand.clone(), 9, zerofy.clone(), Move::Right),
54        // Set second l_shift and stop execution
55        (9, stand.clone(), 0, l_shift.clone(), Move::None),
56    ])?;
57
58    let hyper_machine = Classic::new(program, stand.clone())?;
59    let choose_second = Tape::new([
60        r_shift.clone(),
61        trans.clone(),
62        zerofy.clone(),
63        l_shift.clone(),
64    ]);
65    let result_choose_third = hyper_machine.translate_nrm(choose_second)?;
66
67    let expected_choose_third = Tape::new([
68        r_shift.clone(),
69        r_shift.clone(),
70        trans.clone(),
71        zerofy.clone(),
72        l_shift.clone(),
73        trans.clone(),
74        zerofy.clone(),
75        l_shift.clone(),
76    ]);
77
78    assert_eq!(expected_choose_third, result_choose_third);
79    println!("If you're reading this, hyper machine successful transform choose second machine");
80
81    let tape = Tape::from("0101101110");
82    let mut conf = Configuration::new_nrm(tape.clone())?;
83    for machine in result_choose_third.as_vec() {
84        conf = machine.execute(conf).unwrap();
85        conf.state = State(1)
86    }
87    println!(
88        "Choose third machine translate {} into {}",
89        String::from_iter(tape.as_vec()),
90        String::from_iter(conf.tape().as_vec())
91    );
92
93    Ok(())
94}
Source

fn translate_std(&self, tape: Tape<S>) -> Result<Tape<S>, String>

Translates and returns a mutated Tape using the TuringMachine::execute method as the Configuration::new_std.

Examples found in repository?
examples/binary_addition.rs (line 67)
11fn main() -> Result<(), String> {
12    let mut program = Program::new(vec![' ', '0', '1', '+'], State(8));
13    program.extend([
14        // Sub 1, also init zero check
15        (1, ' ', 0, ' ', Move::None),
16        (1, '0', 1, '0', Move::Left),
17        (1, '1', 2, '0', Move::Right),
18        (1, '+', 6, '+', Move::Right),
19        // Subs part
20        (2, ' ', 3, ' ', Move::Left),
21        (2, '0', 2, '1', Move::Right),
22        // 2, '1' -> Impl
23        // 2, '+' -> Err
24        //
25        // Find + on left
26        // 3, ' ' -> Err
27        (3, '0', 3, '0', Move::Left),
28        (3, '1', 3, '1', Move::Left),
29        (3, '+', 4, '+', Move::Left),
30        // Add 1
31        (4, ' ', 5, '1', Move::Right),
32        (4, '0', 5, '1', Move::Right),
33        (4, '1', 4, '0', Move::Left),
34        // 4, '+' -> Err
35        //
36        // Find + on rigth
37        // 5, ' ' -> Imp
38        (5, '0', 5, '0', Move::Right),
39        (5, '1', 5, '1', Move::Right),
40        (5, '+', 6, '+', Move::Right),
41        // Zero check
42        (6, ' ', 8, ' ', Move::Left),
43        (6, '0', 6, '0', Move::Right),
44        (6, '1', 7, '1', Move::Right),
45        // 6, '+' -> Err
46        //
47        // Find last num
48        (7, ' ', 1, ' ', Move::Left),
49        (7, '0', 7, '0', Move::Right),
50        (7, '1', 7, '1', Move::Right),
51        // 7, '+' -> Err
52        //
53        // Clear + and after
54        // 8, ' ' - Imp
55        (8, '0', 8, ' ', Move::Left),
56        // 8, '1' - Imp
57        (8, '+', 0, ' ', Move::Right),
58    ])?;
59    let machine = Classic::new(program, ' ')?;
60
61    // Change and try to run this example!
62    let lhs = "10101";
63    let rhs = "111";
64    // -----------------------------------
65    let tape = Tape::from(format!("{}+{}", lhs, rhs));
66
67    let res = machine.translate_std(tape)?;
68    println!("{} + {} = {}", lhs, rhs, String::from_iter(res.as_vec()));
69
70    Ok(())
71}
Source

fn translate_nrm(&self, tape: Tape<S>) -> Result<Tape<S>, String>

Translates and returns a mutated Tape using the TuringMachine::execute method as the Configuration::new_nrm.

Examples found in repository?
examples/nice_test.rs (line 28)
11fn main() -> Result<(), String> {
12    let alphabet = vec!['t', 'e', 's', 'n', 'i', 'c', 'e', '_'];
13    let mut program = Program::new(alphabet, State(4));
14    program.extend([
15        (1, 't', 2, 'n', Move::Right),
16        (2, 'e', 3, 'i', Move::Right),
17        (3, 's', 4, 'c', Move::Right),
18        (4, 't', 0, 'e', Move::None),
19        // Revers
20        (1, 'n', 2, 't', Move::Right),
21        (2, 'i', 3, 'e', Move::Right),
22        (3, 'c', 4, 's', Move::Right),
23        (4, 'e', 0, 't', Move::None),
24    ])?;
25    let machine = Classic::new(program, '_')?;
26
27    let test = Tape::from("test");
28    let nice = machine.translate_nrm(test.clone())?;
29    println!(
30        "{} {}!",
31        String::from_iter(nice.as_vec()),
32        String::from_iter(test.as_vec())
33    );
34    Ok(())
35}
More examples
Hide additional examples
examples/hyper_machine.rs (line 65)
11fn main() -> Result<(), String> {
12    use nrm_machines::*;
13
14    let stand = new_stand_machine();
15    let zerofy = new_zerofy_machine();
16    let l_shift = new_left_shift_machine();
17    let r_shift = new_right_shift_machine();
18    let trans = new_trans_machine();
19
20    let mut program = Program::new(
21        vec![
22            stand.clone(),
23            zerofy.clone(),
24            l_shift.clone(),
25            r_shift.clone(),
26            trans.clone(),
27        ],
28        State(9),
29    );
30    // This is simplest implementation of `change choose second to choose third` machine
31    program.extend([
32        // Find l_shift
33        (1, r_shift.clone(), 1, r_shift.clone(), Move::Right),
34        (1, trans.clone(), 1, trans.clone(), Move::Right),
35        (1, zerofy.clone(), 1, zerofy.clone(), Move::Right),
36        (1, l_shift.clone(), 2, stand.clone(), Move::Left),
37        // Clear until r_shift
38        (2, zerofy.clone(), 2, stand.clone(), Move::Left),
39        (2, trans.clone(), 2, stand.clone(), Move::Left),
40        (2, r_shift.clone(), 3, r_shift.clone(), Move::Right),
41        //
42        // Set second r_shift
43        (3, stand.clone(), 4, r_shift.clone(), Move::Right),
44        // Set first trans
45        (4, stand.clone(), 5, trans.clone(), Move::Right),
46        // Set first zerofy
47        (5, stand.clone(), 6, zerofy.clone(), Move::Right),
48        // Set first l_shift
49        (6, stand.clone(), 7, l_shift.clone(), Move::Right),
50        // Set second trans
51        (7, stand.clone(), 8, trans.clone(), Move::Right),
52        // Set second zerofy
53        (8, stand.clone(), 9, zerofy.clone(), Move::Right),
54        // Set second l_shift and stop execution
55        (9, stand.clone(), 0, l_shift.clone(), Move::None),
56    ])?;
57
58    let hyper_machine = Classic::new(program, stand.clone())?;
59    let choose_second = Tape::new([
60        r_shift.clone(),
61        trans.clone(),
62        zerofy.clone(),
63        l_shift.clone(),
64    ]);
65    let result_choose_third = hyper_machine.translate_nrm(choose_second)?;
66
67    let expected_choose_third = Tape::new([
68        r_shift.clone(),
69        r_shift.clone(),
70        trans.clone(),
71        zerofy.clone(),
72        l_shift.clone(),
73        trans.clone(),
74        zerofy.clone(),
75        l_shift.clone(),
76    ]);
77
78    assert_eq!(expected_choose_third, result_choose_third);
79    println!("If you're reading this, hyper machine successful transform choose second machine");
80
81    let tape = Tape::from("0101101110");
82    let mut conf = Configuration::new_nrm(tape.clone())?;
83    for machine in result_choose_third.as_vec() {
84        conf = machine.execute(conf).unwrap();
85        conf.state = State(1)
86    }
87    println!(
88        "Choose third machine translate {} into {}",
89        String::from_iter(tape.as_vec()),
90        String::from_iter(conf.tape().as_vec())
91    );
92
93    Ok(())
94}

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<Machine, S: Symbol> TuringMachine<S> for Debugger<Machine, S>
where Machine: TuringMachine<S>,

Source§

impl<S: Symbol> TuringMachine<S> for Classic<S>