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::Configuration
s and translate
crate::state::Tape
s.
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§
Sourcefn execute_once(
&self,
conf: Configuration<S>,
) -> Result<Configuration<S>, String>
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.
Sourcefn execute_until(
&self,
conf: Configuration<S>,
until: impl Fn(&Configuration<S>) -> bool,
) -> Result<Configuration<S>, String>
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§
Sourcefn execute(&self, conf: Configuration<S>) -> Result<Configuration<S>, String>
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?
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}
Sourcefn translate_std(&self, tape: Tape<S>) -> Result<Tape<S>, String>
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?
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}
Sourcefn translate_nrm(&self, tape: Tape<S>) -> Result<Tape<S>, String>
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?
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
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.