- A 'tape' as a model for computation is a sequence of cells, where something can be written or read from each cell. We talk about the sequence as though written on paper, running from left to right. The elements in the sequence have neighbors, so the sequence of cells can be said to be mutually connected. This is to say that if cell B is to the right of cell A in the sequence, then cell A is to the left of cell B; Also if cell A is to the left of cell B, then cell B is to the right of cell A.
+Tape
- One of the cells on the tape is specially marked as being the 'mounted cell'. This is the cell that can be written or read after the tape is mounted on a 'tape machine', and before any steps have been taken.
+ A 'tape' is a one dimensional discrete space. Being a discrete space, rather than having points, it has 'cells'.
- Information from the `topology` method will remain valid for as long as the topology of
- the tape is not modified.
+ Rather than a function definition assigning a value to a point, and evaluating a function resulting in reading that value back, in a discrete space, a machine writes a value to a cell, and then upon revisiting the cell it can read the value back. The cell that the machine is reading or writing, is the 'cell the head is on'. The machine domain is then the 'tape'.
- A finite tape will have a leftmost cell, which has no left neighbor, and a rightmost cell, which has no right neighbor. All other cells will have two neighbors.
+ A 'tape' is any manifold where each cell has two neighbors, there are two possible such manifolds, either a finite number of cells linked in a cycle, or an unbounded number of cells. A third candidate, the null manifold, does not violate the two neighbor requirements, nor does it fulfill them..
- A tape can have an infinite number of cells to the left of the mount point, to the right of the mount point, or in both directions. Hence it is possible that two, one, or zero cells on a tape have only one neighbor, where the zero neighbor case is for finite tapes, and the latter cases are for infinite tapes.
+ Experience with physical memory tapes guides our abstraction of a tape as a mathematical entity. Note that physicals tapes can have no cells. Two examples include unformated tapes and short tapes that have leaders for mounting on the machine, but after being mounted, do not have sufficient length to be written to. This can happen physically, or logically if more than one volume shares a given tape. Hence, our analogy supports the idea of having a null tape, one with no cells, as an entity.
- An algorithm running on a tape machine that has a left going tape can be translated into an algorithm for a right going tape simply by swapping `step_right` for `step_left`. Hence there is no utility to be had by keeping both models.
+ Given a tape we can prove it to be either a cycle or unbounded by analyzing the situation of mounting the tape on a tape machine and stepping. If by analysis we can proves that when starting at the mount point cell, that stepping in one direction eventually leads back to the mount point cell, then the tape is a cycle. On the other hand if we can prove that will not happen, the tape is unbounded. Note, we must use analysis rather than running the machine, because when stepping the machine in the unbounded case, it will never halt. This is a form of hmotropy analysis of our manifold, with the stepping machine representing a limit.
- Another isomorphism can be setup between a single ended tape and a double direction tape by replacing each step by two steps, and then placing odd cell into correspondence with the right going tape, and even cells with left going tape. Hence an algorithm implemented over the top of either can be mechanically transformed to an algorithm for the other.
+ Suppose we have an unbounded tape. We can create a new manifold by cutting the tape, thus producing to two half tapes, each singly ended though still countably infinite in length. Such a manifold is equivalent to a 'sequence' in mathematics. Both of these manifolds are equivalent to the original uncut manifold. We can see this by taking a sequence and placing every other cell in correspondence to cells on the original tape, alternately mapping to the next consecutive cell on the right going side, then on the left going side.
- However, what we can not do without affecting the power of our computation machine is to
- eliminate 'step-left', yet this is a common simplification in data structures. The Lisp language is based on single linked lists for example.
+ We can take the right going tape and cut it again, to create a finite tape segment, and another right going infinite tape which we let drop to the cutting floor. The finite segment is not equivalent to the original tape of course, as any at mapping all the cells from each tape, will exhaust all the cells on the finite tape with cells left over on the unbounded one. It is interesting to note that the right going tape we left on the floor is in fact equivalent to the tape it was cut from.
- This 'Step Right Machine' (SRM) defined here can only be stepped to the right. Thus whether cells are mutually connected, or not, becomes irrelevant. Also, saying 'leftmost' is a feature of the tape, becomes muddled, as the mount point cell will be the leftmost cell that is ever visited.
+ The finite tape of at least two cells will have two cells that have only one neighbor, the leftmost and the rightmost cell. This manifold is equivalent to a vector variable in mathematics. If merely one cell is shaved off, this singleton tape will have no neighbors. This is equivalent to a variable in mathematics.
- A SRM can be defined using functions, or it can be used as an iterator for traversing through a container.
+ Hence, a half tape manifold can be null, singleton, cyclic, or infinite.
- The property methods defined here are kept general so that they can be used with other tape machines.
+---
+Singly Linked Tape
------
+ Consider a tape where each cell has one right neighbor instead of two mutual neighbors.
-public void lenient_mount() {
- if(status() != Status.TAPE_NOT_MOUNTED) {
- dismount(); // Ensure the current tape is dismounted first
- }
- mount(); // Proceed to mount the new tape
-}
+ When mounted on a tape machine, the mount point cell is the leftmost cell, because the machine can not step left because there is no left neighbor.
-public void lenient_dismount() {
- if(status() != Status.TAPE_NOT_MOUNTED) {
- dismount(); // Only dismount if a tape is currently mounted
- }
-}
-Why This Works Without synchronized:
-Thread Safety via LockManagerDelegate:
+ When cut, we do not get two infinite singly linked tapes, instead we jump ahead to
+ the case of the two parts being an a finite segment, and an infinite right going tail.
-LockManagerDelegate manages locks and ensures that only one thread can operate on the tape at a time.
-When relinquish or request is called, the delegate ensures proper locking/unlocking.
-No Shared State Changes in SRM Methods:
+ In the case of the doubly linked tape, the only way a tape could be cyclic while each cell has two local mutually connected neighbors, is if all the cells are connected in one big cycle. For the singly linked tape, there are no mutual connections, so a cycle can be created by a cell assigning a right neighbor to any other cell already on the tape, including itself. Hence, the Singly Linked Tape has three possible cycle cases. However, for the
+ state machine methods behave the same for all three.
-The SRM methods (mount, dismount, lenient_mount, lenient_dismount) simply delegate to LockManagerDelegate and update internal state like Status. There’s no risk of race conditions if the delegate properly handles concurrent access.
-Relinquishing Locks Last:
+ Also for the single linked machine, the Singleton manifold and the Rightmost manifold
+ become identical.
-By ensuring that relinquish is the last step in dismount and other relevant methods, we prevent premature lock release before operations are complete.
+ Hence these are the possible manifolds for a singly linked tape:
+ null, cyclic, segment, or infinite.
-----
-a SRM with a function implementation represents an evolving system, it is common that information is lost for reversing a forward step in an evolving system, so it is natural in function based programming to have a tape machine that only steps right.
+
+ A machine with a singly linked tape mounted, can not compute some things that a Turing Machine can, yet, it is a common data structure used in computing. It can be used with forward, irreversible, advance of a program. This is the most common kind actually. If local reversibility is needed, a cache or window can be used for recent values. The depth of this local memory is an interesting metric. For macro level reversibility, a system can use checkpoints.
-Still a Turing Machine can step left, and there are computation complexity implications. Some of these can be mitigated by having a context window, and thus tentative forward evolution of the system.
+---
+
+The Step Right Machine
+
+ This is a conventional iterator for traversing through containers. The items visited
+ during the traversal are as though values in cells on a single linked tape.
+
+
+---------------------------------------
+
+Tape Topology
+
+A tape is a one-dimensional discrete space consisting of "cells." These cells represent the fundamental units of memory that a machine can read from or write to. The set of all cells defines the tape topology, which determines the connectivity and traversal characteristics of the tape.
+
+Key Characteristics of Tape Topologies
+1. Stepping Determines Topology:
+ - A machine begins at the leftmost cell when the tape is mounted. Stepping right from this cell reveals the connectivity of the tape. This process is analogous to "shrinking the circle" in topology, where stepping serves as an operation to explore and classify the tape's structure.
+
+2. Single-ended Constraint:
+ - A tape is always single-ended because there is no cell to the left of the leftmost cell. This rules out two-way infinite tapes, as there is no way to step left.
+
+3. Unbroken Connectivity:
+ - The tape is either unbounded (infinite), cyclic (all cells connect into a single cycle), or finite (with distinct leftmost and rightmost boundaries). If stepping reaches a cell that is not connected to any other cell, that cell is the rightmost cell of a finite tape segment.
+
+Defined Topologies
+
+State can_read() can_step() Notes
+Null false false No cells exist; the machine cannot perform any operation.
+Cyclic true true The machine loops indefinitely, can always read and step.
+Segment true true (until rightmost) Represents a bounded tape; steps until reaching the rightmost cell.
+Infinite Right true true Unbounded cells extend infinitely; can always read and step.
+Rightmost true false At the last cell of a finite segment (or singleton tape).
+
+---
+🥳 Cheers to:
+
+A precise loop that doesn’t compromise readability or efficiency.
+An elegant state pattern that aligns with the real-world model.
+The beauty of RT code format guiding clarity and consistency!
import java.math.BigInteger;
-public class CountingNumber {
+public class CountingNumber extends Ariadne_SRM<BigInteger>{
private BigInteger i;
private BigInteger maximum;
- private State current_state;
- public static CountingNumber make( BigInteger maximum ){
- return new CountingNumber( maximum );
- }
+ private final State state_null = new State_Null();
+ private final State state_segment = new State_Segment();
+ private final State state_rightmost = new State_Rightmost();
+ private final State state_infinite = new State_Infinite();
- public static CountingNumber make(){
- return new CountingNumber( null );
- }
-
- private CountingNumber( BigInteger maximum ){
+ private CountingNumber(BigInteger maximum){
this.i = BigInteger.ONE;
this.maximum = maximum;
- this.current_state = ( maximum == null ) ? new State_InfiniteRight() : new State_Leftmost();
- }
- private void set_state( State new_state ){
- this.current_state = new_state;
- }
-
- public boolean can_read(){
- return current_state.can_read();
+ if( maximum == null ){
+ set_state(state_infinite);
+ }else if( maximum.compareTo(BigInteger.ZERO) <= 0 ){
+ set_state(state_null);
+ }else if( maximum.equals(BigInteger.ONE) ){
+ set_state(state_rightmost);
+ }else{
+ set_state(state_segment);
+ }
}
- public boolean can_step(){
- return current_state.can_step();
+ public static CountingNumber make(BigInteger maximum){
+ return new CountingNumber(maximum);
}
- public void step(){
- current_state.step();
+ public static CountingNumber make(){
+ return new CountingNumber(null);
}
+ @Override
public BigInteger read(){
return i;
}
- // --- State Interface ---
- private abstract class State {
- abstract boolean can_read();
- abstract boolean can_step();
- abstract void step();
+ private abstract class BaseState extends State{
+ abstract MachineState state();
}
- // --- State_Leftmost ---
- private class State_Leftmost extends State {
+ private class State_Null extends BaseState{
@Override
boolean can_read(){
- return true;
+ return false;
}
-
@Override
boolean can_step(){
- return true;
+ return false;
}
-
@Override
void step(){
- i = i.add( BigInteger.ONE );
- if( i.equals( maximum ) ){
- set_state( new State_Rightmost() );
- }else{
- set_state( new State_InterimSegment() );
- }
+ throw new UnsupportedOperationException("Cannot step from NULL state.");
+ }
+ @Override
+ MachineState state(){
+ return MachineState.NULL;
}
}
- // --- State_InterimSegment ---
- private class State_InterimSegment extends State {
+ private class State_Segment extends BaseState{
@Override
boolean can_read(){
return true;
}
-
@Override
boolean can_step(){
return true;
}
-
@Override
void step(){
- i = i.add( BigInteger.ONE );
- if( i.equals( maximum ) ){
- set_state( new State_Rightmost() );
+ i = i.add(BigInteger.ONE);
+ if( i.equals(maximum) ){
+ set_state(state_rightmost);
}
}
+ @Override
+ MachineState state(){
+ return MachineState.SEGMENT;
+ }
}
- // --- State_InfiniteRight ---
- private class State_InfiniteRight extends State {
+ private class State_Rightmost extends BaseState{
@Override
boolean can_read(){
return true;
}
-
@Override
boolean can_step(){
- return true;
+ return false;
}
-
@Override
void step(){
- i = i.add( BigInteger.ONE );
+ throw new UnsupportedOperationException("Cannot step from RIGHTMOST.");
+ }
+ @Override
+ MachineState state(){
+ return MachineState.RIGHTMOST;
}
}
- // --- State_Rightmost ---
- private class State_Rightmost extends State {
+ private class State_Infinite extends BaseState{
@Override
boolean can_read(){
return true;
}
-
@Override
boolean can_step(){
- return false;
+ return true;
}
-
@Override
void step(){
- throw new UnsupportedOperationException( "Cannot step from RIGHTMOST." );
+ i = i.add(BigInteger.ONE);
+ }
+ @Override
+ MachineState state(){
+ return MachineState.INFINITE;
}
}
+
}
--- /dev/null
+#!/bin/bash
+java Example_CountingNumber_0
-import com.ReasoningTechnology.Ariadne.Ariadne_SRM;
import java.math.BigInteger;
-public class Example_CountingNumber_0 {
+public class Example_CountingNumber_0{
- protected static void print_ten(CountingNumber n) {
+ protected static void print_ten(CountingNumber n){
System.out.println("Iterating through Counting Numbers:");
- if (!n.can_read()) return;
-
- if (n.topology() == Ariadne_SRM.Topology.SEGMENT) {
- if (n.can_read()) {
- do {
- System.out.println("Current Number: " + n.read());
- if (!n.can_step()) break;
- n.step();
- } while (true);
- }
- } else if (n.topology() == Ariadne_SRM.Topology.INFINITE_RIGHT) {
- int i = 1;
- if (n.can_read()) {
- do {
- System.out.println("Current Number: " + n.read());
- if (i == 10) break;
- n.step();
- i++;
- } while (true);
- }
- } else {
- System.out.println("Unrecognized tape topology.");
+
+ if( !n.can_read() ) return;
+
+ if( n.state() == Ariadne_SRM.MachineState.SEGMENT ){
+ do{
+ System.out.println("Current Number: " + n.read());
+ if( !n.can_step() ) break;
+ n.step();
+ }while( true );
+
+ }else if( n.state() == Ariadne_SRM.MachineState.INFINITE ){
+ int count = 0;
+ do{
+ System.out.println("Current Number: " + n.read());
+ if( count == 9 ) break;
+ n.step();
+ count++;
+ }while( true );
+
+ }else{
+ System.out.println("Unrecognized or invalid tape state.");
}
}
- public static void main(String[] args) {
- print_ten(CountingNumber.make(BigInteger.TEN));
- print_ten(CountingNumber.make());
+ public static void main(String[] args){
+ print_ten( CountingNumber.make(BigInteger.TEN) ); // Finite segment up to 10
+ print_ten( CountingNumber.make() ); // Infinite tape, stopping after 10 steps
}
+
}
--- /dev/null
+#!/bin/bash
+java Example_IndexTree_Diagonal_SRM
--- /dev/null
+#!/bin/bash
+java Example_SRMI_Array
--- /dev/null
+#!/bin/bash
+java Example_SRM_List
This is a mostly abstract base class.
- This is for single threaded execution. The multiple thread model
+ This is for single-threaded execution. The multi-threaded model
uses `mount` and `dismount` to lock the resources being iterated on.
-
*/
-package com.ReasoningTechnology.Ariadne;
-
-public class Ariadne_SRM<TElement> {
-
- public static <TElement> Ariadne_SRM<TElement> make(){
- return new Ariadne_SRM<>();
- }
- protected Ariadne_SRM(){
- }
-
- // machine and tape status/properties
- //
+public abstract class Ariadne_SRM<T>{
- public enum Topology{
- UNDEFINED
- ,NO_CELLS
- ,SINGLETON
+ public enum MachineState{
+ NULL
+ ,CYCLIC
,SEGMENT
- ,SEGMENT_OR_CIRCLE
- ,CIRCLE
- ,CIRCLE_OR_INFINITE_RIGHT
- ,INFINITE_RIGHT
- ;
- }
- public enum Location{
- OTHER
- ,LEFTMOST
- ,INTERIM
,RIGHTMOST
+ ,INFINITE
;
}
- public Topology topology(){
- return Topology.UNDEFINED;
- }
- public Location location(){
- throw new UnsupportedOperationException("Ariadne_SRM::location not implemented.");
- }
- public boolean can_step() {
- return topology().ordinal() >= Topology.SEGMENT.ordinal()
- && location().ordinal() <= Location.INTERIM.ordinal();
- }
- public boolean can_read() {
- return topology().ordinal() >= Topology.SINGLETON.ordinal();
- }
-
- // moving the head
- //
-
- public void step(){
- throw new UnsupportedOperationException("Ariadne_SRM::step not implemented.");
+ protected abstract class State{
+ abstract boolean can_read();
+ abstract boolean can_step();
+ abstract void step();
+ abstract MachineState state();
}
- public void rewind(){
- throw new UnsupportedOperationException("Ariadne_SRM::rewind not implemented.");
- }
+ private State current_state;
- public void fast_forward(){
- throw new UnsupportedOperationException("Ariadne_SRM::fast_forward not implemented.");
+ protected void set_state(State new_state){
+ this.current_state = new_state;
}
- // access
- //
-
- public TElement access(){
- // returns a reference, cell can then be read or written
- throw new UnsupportedOperationException("Ariadne_SRM::read not implemented.");
+ public boolean can_read(){
+ return current_state.can_read();
}
-
- public TElement read(){
- TElement accessed_cell = access();
- return deep_copy( accessed_cell );
+ public boolean can_step(){
+ return current_state.can_step();
}
- private TElement deep_copy( TElement original ){
- throw new UnsupportedOperationException("Ariadne_SRM::deep_copy not implemented.");
+ public void step(){
+ current_state.step();
}
-
- // writes value
- public void write(TElement e){
- throw new UnsupportedOperationException("Ariadne_SRM::read not implemented.");
+ public MachineState state(){
+ return current_state.state();
}
+ public abstract T read();
}
+