Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V0.0.3 #8

Merged
merged 36 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/crates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ on:
workflow_dispatch:

jobs:
independents:
base:
env:
CRATE_NAME: ${{ github.event.repository.name }}-${{ matrix.suffix }}
name: Publish (${{ matrix.suffix }})
Expand All @@ -42,6 +42,7 @@ jobs:
- run: cargo publish --all-features -v -p ${{ env.CRATE_NAME }} --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
publish:
name: Publish (${{ github.event.repository.name }})
needs: base
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ thiserror = "1"

[workspace.package]
authors = ["Joe McCain III <jo3mccain@icloud.com>",]
categories = [ ]
categories = [ "mathematics", "science", "simulation" ]
description = "This crate focuses on building concrete implementations for Turing Machines."
edition = "2021"
homepage = "https://github.com/FL03/rstm/wiki"
keywords = [ ]
keywords = [ "turing", "turing-machine", "utm" ]
license = "Apache-2.0"
readme = "README.md"
repository = "https://github.com/FL03/rstm.git"
version = "0.0.2"
version = "0.0.3"

[profile.dev]
opt-level = 0
Expand Down
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,27 @@ cargo build --features full -r --workspace
```rust
extern crate rstm;

fn main() -> Result<(), Box<dyn std::error::Error>> {
use rstm::state::BinState::{Invalid, Valid};
use rstm::{rule, Program, State, StdTape, TM};

fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt().with_target(false).init();

// initialize the tape data
let alpha: Vec<u8> = vec![1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1];
// define the rules for the machine
let rules = vec![
rule![(Invalid, 0) -> Right(Invalid, 0)],
rule![(Invalid, 1) -> Right(Valid, 0)],
rule![(Valid, 0) -> Right(Valid, 1)],
rule![(Valid, 1) -> Left(Valid, 0)],
];

let tape = StdTape::from_iter(alpha);
let program = Program::from_state(State(Invalid)).with_instructions(rules);
// create a new instance of the machine
let tm = TM::new(program, tape);
tm.execute()?;
Ok(())
}
```
Expand Down
195 changes: 195 additions & 0 deletions core/src/actors/actor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/*
Appellation: actor <module>
Contrib: FL03 <jo3mccain@icloud.com>
*/
#[doc(inline)]
pub use self::builder::ActorBuilder;

use super::Executor;
use crate::rules::{Directive, Program};
use crate::{Head, State};

/// An [Actor] describes a Turing machine with a moving head (TMH).
#[derive(Clone, Debug)]
pub struct Actor<Q, S> {
/// the input alphabet
pub(crate) alpha: Vec<S>,
/// the head of the tape
pub(crate) head: Head<Q, usize>,
}

impl<Q, S> Actor<Q, S> {
Fixed Show fixed Hide fixed
pub fn new() -> ActorBuilder<Q, S> {
ActorBuilder::new()
}
Fixed Show fixed Hide fixed
Comment on lines +24 to +26

Check warning

Code scanning / clippy

methods called new usually return Self Warning

methods called new usually return Self

pub fn from_state(State(state): State<Q>) -> ActorBuilder<Q, S> {
ActorBuilder::from_state(State(state))
}
/// Returns an immutable reference to the tape alphabet as a slice
pub fn alpha(&self) -> &[S] {
&self.alpha
}
/// Returns an immutable reference to the head of the tape
pub const fn head(&self) -> &Head<Q, usize> {
&self.head
}

pub fn head_ref(&self) -> Head<&Q, usize> {
Head {
state: self.head.state.to_ref(),
symbol: self.head.symbol,
}
}
/// Returns a mutable reference to the head of the tape
pub fn head_mut(&mut self) -> &mut Head<Q, usize> {
&mut self.head
}
/// Returns the current state of the tape
pub fn state(&self) -> State<&Q> {
self.head.state()
}
/// Returns a mutable reference to the current state of the tape
pub fn state_mut(&mut self) -> State<&mut Q> {
self.head.state_mut()
}
/// Performs a single step of the Turing machine
#[cfg_attr(
feature = "tracing",
tracing::instrument(skip_all, name = "step", target = "actor")
)]
pub fn step<D>(&mut self, rule: &D) -> Option<Head<&Q, &S>>
where
D: Directive<Q, S>,
S: Clone,
{
self.write(rule.value().clone());
Fixed Show fixed Hide fixed
self.head.shift_inplace(rule.direction());
self.read()
}
/// Executes the given program; the method is lazy, meaning it will not compute immediately
/// but will return an [Executor] that is better suited for managing the runtime.
pub fn execute(self, program: Program<Q, S>) -> Executor<Q, S> {
Executor::new(self, program)
}
/// Checks if the tape is empty
pub fn is_empty(&self) -> bool {
self.alpha.is_empty()
}
/// Checks if the tape is halted
pub fn is_halted(&self) -> bool
where
Q: 'static,
{
self.head.state.is_halt()
}
/// Returns the length of the tape
#[inline]
pub fn len(&self) -> usize {
Fixed Show fixed Hide fixed
self.alpha.len()
}
/// Reads the current symbol at the head of the tape
#[cfg_attr(
feature = "tracing",
tracing::instrument(skip_all, name = "read", target = "actor")
)]
pub fn read(&self) -> Option<Head<&Q, &S>> {
#[cfg(feature = "tracing")]
tracing::info!("Reading the tape...");
let Head { state, symbol } = self.head_ref();
self.alpha.get(symbol).map(|value| Head::new(state, value))
}
/// Writes the given symbol to the tape
#[cfg_attr(
feature = "tracing",
tracing::instrument(skip_all, name = "write", target = "actor")
)]
pub fn write(&mut self, value: S) {
let pos = self.head.symbol;
if pos < self.len() {
self.alpha[pos] = value;
} else {
#[cfg(feature = "tracing")]
tracing::info!("Appending to the tape...");
// append to the tape
self.alpha.push(value);
}
}
}

mod builder {
use super::*;
use std::iter::FromIterator;

#[derive(Default)]
pub struct ActorBuilder<Q, S> {
alpha: Vec<S>,
state: Option<State<Q>>,
symbol: usize,
}

impl<Q, S> ActorBuilder<Q, S> {
pub fn new() -> Self {
Self {
alpha: Vec::new(),
state: None,
symbol: 0,
}
}

pub fn from_state(State(state): State<Q>) -> Self {
Self {
alpha: Vec::new(),
state: Some(State(state)),
symbol: 0,
}
}

pub fn alpha<I>(self, alpha: I) -> Self
where
I: IntoIterator<Item = S>,
{
Self {
alpha: Vec::from_iter(alpha),
..self
}
}

pub fn head(self, head: Head<Q, usize>) -> Self {
Self {
state: Some(head.state),
symbol: head.symbol,
..self
}
}

pub fn state(self, State(state): State<Q>) -> Self {
Self {
state: Some(State(state)),
..self
}
}

pub fn position(self, symbol: usize) -> Self {
Self { symbol, ..self }
}

pub fn build(self) -> Actor<Q, S>
where
Q: Default,
{
let ActorBuilder {
alpha,
state,
symbol,
} = self;
Actor {
alpha,
head: Head {
state: state.unwrap_or_default(),
symbol,
},
}
}
}
}
78 changes: 78 additions & 0 deletions core/src/actors/exec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
Appellation: exec <module>
Contrib: FL03 <jo3mccain@icloud.com>
*/
use super::Actor;
use crate::{Error, Head, Program, Symbolic};

pub struct Executor<Q, S> {
pub(crate) actor: Actor<Q, S>,
pub(crate) program: Program<Q, S>,
}

impl<Q, S> Executor<Q, S> {
pub(crate) fn new(actor: Actor<Q, S>, program: Program<Q, S>) -> Self {
Self { actor, program }
}
pub fn from_actor(actor: Actor<Q, S>) -> Self
where
Q: Default,
{
Self {
actor,
program: Program::new(),
}
}

pub fn with_program(self, program: Program<Q, S>) -> Self {
Executor { program, ..self }
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(skip_all, name = "run", target = "actor")
)]
pub fn run(&mut self) -> Result<Vec<S>, Error>
where
Q: Clone + PartialEq + 'static,
S: Symbolic,
{
#[cfg(feature = "tracing")]
tracing::info!("Executing the program using the given actor...");
loop {
match self.next() {
Some(_) => continue,
None => {
if self.actor.is_halted() {
break;
} else {
return Err(Error::runtime_error("Unknown Error".to_string()));
}
}
}
}
Ok(self.actor.alpha().to_vec())
}
}

impl<Q, S> Iterator for Executor<Q, S>
where
Q: Clone + PartialEq + 'static,
S: Symbolic,
{
type Item = Head<Q, S>;

#[cfg_attr(
feature = "tracing",
tracing::instrument(skip_all, name = "next", target = "actor")
)]
fn next(&mut self) -> Option<Self::Item> {
if self.actor.is_halted() {
#[cfg(feature = "tracing")]
tracing::info!("Halted");
return None;
}
let Head { state, symbol } = self.actor.read()?;
let rule = self.program.get(state, symbol)?;
self.actor.step(rule).map(|h| h.cloned())
}
}
14 changes: 14 additions & 0 deletions core/src/actors/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
Appellation: actors <module>
Contrib: FL03 <jo3mccain@icloud.com>
*/
#[doc(inline)]
pub use self::{actor::Actor, exec::Executor};

pub(crate) mod actor;
pub(crate) mod exec;

pub(crate) mod prelude {
pub use super::actor::Actor;
pub use super::exec::Executor;
}
Loading
Loading