--- /dev/null
+package com.ReasoningTechnology.Ariadne;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+public class Ariadne_GraphDirectedAcyclic extends Ariadne_Graph{
+
+ // test messaging
+ //
+ private static boolean test = false;
+ public static void test_switch(boolean test){
+ if(Ariadne_Graph.test && !test){
+ test_print("Ariadne_Graph:: test messages off");
+ }
+ if(!Ariadne_Graph.test && test){
+ test_print("Ariadne_Graph:: test messages on");
+ }
+ }
+ private static void test_print(String message){
+ if(test){
+ System.out.println(message);
+ }
+ }
+
+ // class data
+ //
+
+ // marks this class might put on a node
+ public static Ariadne_TokenSet node_marks = new Ariadne_TokenSet(){{
+ add(new Ariadne_Token("empty_root_label_list"));
+ add(new Ariadne_Token("cycle_exists"));
+ add(new Ariadne_Token("undefined_node_exists"));
+ add(new Ariadne_Token("bad_descent_termination"));
+ add(new Ariadne_Token("max_depth_reached"));
+ }};
+
+ // graph descend method return values
+ private static Ariadne_TokenSet graph_descend_set = new Ariadne_TokenSet(){{
+ add(new Ariadne_Token("empty_path_stack"));
+ add(new Ariadne_Token("cycle_found"));
+ add(new Ariadne_Token("undefined_node"));
+ add(new Ariadne_Token("leaf"));
+ add(new Ariadne_Token("max_depth_reached"));
+ }};
+
+
+ // instance data
+
+ // constructors
+ //
+ public Ariadne_GraphDirectedAcyclic(){
+ super(new HashMap<>(), null);
+ }
+
+ public Ariadne_GraphDirectedAcyclic(Map<Ariadne_Label, Ariadne_Node> node_map, Ariadne_DefinitionList recognizer_f_list, Ariadne_LabelList root_node_list, int max_depth, boolean verbose){
+ super(node_map, recognizer_f_list);
+ Ariadne_TokenSet cycle_detection_result = graph_mark_cycles(root_node_list, max_depth, verbose);
+ }
+
+ public Ariadne_GraphDirectedAcyclic(Map<Ariadne_Label, Ariadne_Node> node_map, Ariadne_DefinitionList recognizer_f_list, Ariadne_LabelList root_node_list){
+ super(node_map, recognizer_f_list);
+ Ariadne_TokenSet cycle_detection_result = graph_mark_cycles(root_node_list);
+ }
+
+ // interface functions
+ //
+ private List<Integer> path_find_cycle(Ariadne_LabelList path){
+ if(path.size() <= 1) return null;
+
+ int rightmost_index = path.size() - 1;
+ Ariadne_Label rightmost_node_label = path.get(rightmost_index);
+
+ int cycle_leftmost_index = path.indexOf(rightmost_node_label);
+ Boolean has_cycle = cycle_leftmost_index < rightmost_index;
+ if(!has_cycle) return null;
+
+ List<Integer> result = new ArrayList<>();
+ result.add(cycle_leftmost_index);
+ result.add(rightmost_index);
+ return result;
+ }
+
+ private boolean graph_descend_cycle_case(Ariadne_LabelList left_path, List<Ariadne_LabelList> path_stack, boolean verbose){
+
+ List<Integer> cycle_index_interval = path_find_cycle(left_path);
+ if(cycle_index_interval == null){
+ return false;
+ }
+
+ int cycle_i0 = cycle_index_interval.get(0);
+ int cycle_n = cycle_index_interval.get(1);
+
+ if(verbose) Ariadne_Util.print_list(
+ "Found cycle:",
+ left_path.subList(cycle_i0, cycle_n + 1)
+ );
+
+ Ariadne_LabelList undefined_node_list = new Ariadne_LabelList();
+ for (int i = cycle_i0; i <= cycle_n; i++){
+ Ariadne_Label node_label = left_path.get(i);
+ Ariadne_Node node = super.lookup(node_label);
+ if(node != null){
+ node.mark(new Ariadne_Token("cycle_member"));
+ } else{
+ undefined_node_list.add(node_label);
+ }
+ }
+
+ if(verbose) Ariadne_Util.print_list(
+ "Each undefined node could not be marked as a cycle member:",
+ undefined_node_list
+ );
+
+ path_stack.subList(cycle_i0 + 1, cycle_n + 1).clear();
+
+ return true;
+ }
+
+ private Ariadne_TokenSet graph_descend(List<Ariadne_LabelList> path_stack, int max_depth, boolean verbose){
+ Ariadne_TokenSet ret_value = new Ariadne_TokenSet();
+
+ if(path_stack.isEmpty()){
+ ret_value.add(new Ariadne_Token("empty_path_stack"));
+ return ret_value;
+ }
+
+ Ariadne_LabelList left_path = new Ariadne_LabelList();
+ for (Ariadne_LabelList neighbor_list : path_stack){
+ left_path.add(neighbor_list.get(0));
+ }
+
+ do{
+
+ if(graph_descend_cycle_case(left_path, path_stack, verbose)){
+ ret_value.add(new Ariadne_Token("cycle_found"));
+ return ret_value;
+ }
+
+ Ariadne_Label it_node_label = path_stack.get(path_stack.size() - 1).get(0);
+ Ariadne_Node it_node = super.lookup(it_node_label);
+ if(it_node == null){
+ ret_value.add(new Ariadne_Token("undefined_node"));
+ return ret_value;
+ }
+
+ Ariadne_LabelList neighbor_list = it_node.neighbor_LabelList();
+ if(neighbor_list.isEmpty()){
+ ret_value.add(new Ariadne_Token("leaf"));
+ return ret_value;
+ }
+
+ path_stack.add(new Ariadne_LabelList(neighbor_list));
+ Ariadne_Label it_next_label = neighbor_list.get(0);
+ left_path.add(it_next_label);
+
+ if(max_depth > 0){
+ max_depth--;
+ if(max_depth == 0){
+ if(verbose){
+ Ariadne_Util.print_list("GraphDirectedAcyclic.GraphDescend:: max_depth reached, ending descent:", path_stack);
+ }
+ ret_value.add(new Ariadne_Token("max_depth_reached"));
+ return ret_value;
+ }
+ }
+
+ } while (true);
+ }
+
+
+ public Ariadne_TokenSet graph_mark_cycles(Ariadne_LabelList root_node_LabelList, int max_depth, boolean verbose){
+ Ariadne_TokenSet ret_value = new Ariadne_TokenSet();
+ boolean exists_malformed = false;
+ Ariadne_TokenSet result;
+
+ if(root_node_LabelList.isEmpty()){
+ ret_value.add(new Ariadne_Token("empty_root_label_list"));
+ return ret_value;
+ }
+
+ List<Ariadne_LabelList> path_stack = new ArrayList<>();
+ path_stack.add(new Ariadne_LabelList(root_node_LabelList));
+
+ do{
+ result = graph_descend(path_stack, max_depth, verbose);
+ if(result.contains(new Ariadne_Token("cycle_found"))) ret_value.add(new Ariadne_Token("cycle_exists"));
+ if(result.contains(new Ariadne_Token("undefined_node"))) ret_value.add(new Ariadne_Token("undefined_node_exists"));
+ if(result.contains(new Ariadne_Token("max_depth_reached"))) ret_value.add(new Ariadne_Token("max_depth_reached"));
+ if(!result.contains(new Ariadne_Token("leaf")) && !result.contains(new Ariadne_Token("cycle_found"))) ret_value.add(new Ariadne_Token("bad_descent_termination"));
+
+ Ariadne_LabelList top_list = path_stack.get(path_stack.size() - 1);
+ top_list.remove(0);
+ if(top_list.isEmpty()) path_stack.remove(path_stack.size() - 1);
+
+ } while (!path_stack.isEmpty());
+
+ if(verbose){
+ if(ret_value.contains("bad_descent_termination")){
+ System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: terminated with unexpected condition.");
+ }
+ if(ret_value.contains("cycle_exists")){
+ System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: One or more cycles detected.");
+ }
+ if(ret_value.contains("undefined_node_exists")){
+ System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: Undefined nodes exist.");
+ }
+ }
+
+ return ret_value;
+ }
+
+ public Ariadne_TokenSet graph_mark_cycles(Ariadne_LabelList root_node_LabelList){
+ return graph_mark_cycles(root_node_LabelList, this.debug ? 40 : -1, this.debug);
+ }
+
+ @Override
+ public Ariadne_Node lookup(Ariadne_Label node_label, boolean verbose){
+ Ariadne_Node node = super.lookup(node_label, verbose);
+ if(node != null && node.has_mark(new Ariadne_Token("cycle_member"))){
+ if(verbose){
+ System.out.println("GraphDirectedAcyclic.lookup:: Node is part of a cycle, not returned: " + node_label);
+ }
+ return null;
+ }
+ return node;
+ }
+
+ public Ariadne_Node lookup(Ariadne_Label node_label){
+ return lookup(node_label, this.debug);
+ }
+
+}
--- /dev/null
+/*
+SRTM_Depth is a list of neighbor SRTMs going down the leftmost side of
+a graph traversal. A leftmost traversal is one characterized by
+following leftmost not yet visited node on the most recently visited
+node's neighbor list.
+
+Depth traversal from a start node, ends when reaching a node that has
+no neighbors, or when reaching encountering a cycle.
+
+The `Node::neighbor()` function returns an SRTM for iterating over the
+node's neighbors. An SRTM is returned rather than a list, because in
+general a neighbor list is allowed to be unbounded. Though with a
+finite graph, that can not happen. (See IndexTree for an example of an
+infinite depth and infinite breadth graph traveral.)
+
+It is possible to construct and infinite graph such that the
+`SRTM_Depth::make()` function would never return.
+
+For a finite graph, this depth traversal will provably terminate, due
+to running out unique (non cycle) nodes to visit. More generally, if
+graph traversal from a start node is guaranteed to reach a leaf node
+(has no neighbors), or a a cycle, within a finite number of node
+traversal steps, then `SRTM_Depth::make()` will always return.
+
+Each call to step causes the TM read head to move to the next lowest
+depth, leftmost unvisited node. This might require backtracking and
+descending again.
+
+Nodes are referenced by label.
+
+A null valued label is flagged as an error, though we still look it up
+in the graph. It is a fatal error, `exit(1)` if `lookup` returns a
+null node.
+
+A path is a list of nodes found while traversing a tree. A road is a
+list of child_srtm found while traversing the tree.
+
+*/
+
+import com.ReasoningTechnology.Ariadne.Ariadne_SRTM;
+import com.ReasoningTechnology.Ariadne.Ariadne_Graph;
+
+
+class SRTM_Depth{
+
+ // static
+ //
+
+ PathStack make(Graph g){
+ return new SRTM_Depth(g);
+ }
+
+ // instance data
+ //
+ protected List<Ariadne_SRTM> path;
+ protected Graph graph;
+
+ // constructor
+ //
+ protected SRTM_Depth(Graph g){
+ set_topography(topo_null);
+ if(g == null) return;
+ graph = g;
+ path.add( g.start() );
+ descend();
+ }
+
+ // instance interface implementation
+ //
+
+
+ // A path is terminated by a leaf node or discovering a cycle.
+ protected boolean extend_path_to_termination(){
+
+ ArrayList<Label> = path new ArrayList<>;
+
+
+ // Get the label for current child of the deepest in tree child_srtm
+ // The current child is the one under the read head.
+ Ariadne_SRTM<Ariadne_SRTM> child_srtm = path.get(path.size() - 1);
+ Ariande_Label label = child_srtm.read();
+ if( label == null ){
+ System.out.println("SRTM_Depth::extend_to_leaf found null node");
+ }
+
+ // check if label has been visited before:
+ //
+
+
+ // descend from the label and put it in to
+ Ariadne_Node node = graph.lookup(label);
+ if( node == null ){
+ System.out.println
+ (
+ "SRTM_Depth::descend error: label(\""
+ + label
+ + "\") not found in graph."
+ );
+ return false;
+ }
+
+ Ariadne_SRTM_Label = node.neighbor();
+
+ if( !
+
+ Ariadne_SRTM<Ariadne_SRTM> srtm = Ariadna_SRTM_List.make(path);
+ if( !srtm.can_read() ) return;
+ do{
+ child_srtm = srtm.read();
+ if( !srtm.can_step() ) break;
+ srtm.step();
+ }while(true);
+
+ visited.push(path.
+ }
+
+ // being a good object citizen
+ //
+
+
+}
--- /dev/null
+package com.ReasoningTechnology.Ariadne;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SRTM_Depth extends Ariadne_SRTM {
+
+ // Static method to create a depth traversal SRTM
+ public static SRTM_Depth make(Ariadne_Graph graph){
+ SRTM_Depth depth = new SRTM_Depth();
+ depth.path.add(graph.start());
+ depth.descent();
+ return depth;
+ }
+
+ // Instance data
+ private final List<Ariadne_SRTM> path;
+
+ private final TopoIface topo_null = new TopoNull();
+ private final TopoIface topo_segment = new TopoSegment();
+
+ // Constructor
+ protected SRTM_Depth(){
+ this.path = new ArrayList<>();
+ set_topology(topo_null);
+ }
+
+ // Descends to the leftmost unvisited node
+ protected void descent(){
+ while( true ){
+ Ariadne_SRTM current = path.get(path.size() - 1);
+ if( !current.can_read() ){
+ backtrack();
+ if( path.isEmpty() ) return; // No more nodes to traverse
+ continue;
+ }
+
+ Ariadne_SRTM neighbors = current.read(); // Get neighbor SRTM
+ if( neighbors == null || !neighbors.can_read() ){
+ backtrack();
+ if( path.isEmpty() ) return;
+ continue;
+ }
+
+ path.add(neighbors);
+ set_topology(topo_segment);
+ }
+ }
+
+ // Backtracks to the previous node
+ protected void backtrack(){
+ while( !path.isEmpty() ){
+ Ariadne_SRTM last = path.get(path.size() - 1);
+ last.step();
+ if( last.can_step() ){
+ return;
+ }
+ path.remove(path.size() - 1);
+ }
+ set_topology(topo_null);
+ }
+
+ // Steps to the next node in the traversal
+ @Override
+ public void step(){
+ descent();
+ }
+
+ // Reads the current node
+ @Override
+ public Ariadne_SRTM read(){
+ return path.isEmpty() ? null : path.get(path.size() - 1);
+ }
+
+ // Checks if traversal can continue
+ @Override
+ public boolean can_read(){
+ return current_topology.can_read();
+ }
+
+ // Topology: Null
+ private class TopoNull implements TopoIface{
+ @Override public boolean can_read(){
+ return false;
+ }
+ @Override public Object read(){
+ throw new UnsupportedOperationException("Cannot read from NULL topology.");
+ }
+ @Override public boolean can_step(){
+ return false;
+ }
+ @Override public void step(){
+ throw new UnsupportedOperationException("Cannot step from NULL topology.");
+ }
+ @Override public Topology topology(){
+ return Topology.NULL;
+ }
+ }
+
+ // Topology: Segment
+ private class TopoSegment implements TopoIface{
+ @Override public boolean can_read(){
+ return true;
+ }
+ @Override public Object read(){
+ return path.get(path.size() - 1);
+ }
+ @Override public boolean can_step(){
+ return !path.isEmpty();
+ }
+ @Override public void step(){
+ descent();
+ }
+ @Override public Topology topology(){
+ return Topology.SEGMENT;
+ }
+ }
+}
+++ /dev/null
-package com.ReasoningTechnology.Ariadne;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.List;
-import java.util.ArrayList;
-
-public class Ariadne_GraphDirectedAcyclic extends Ariadne_Graph{
-
- // test messaging
- //
- private static boolean test = false;
- public static void test_switch(boolean test){
- if(Ariadne_Graph.test && !test){
- test_print("Ariadne_Graph:: test messages off");
- }
- if(!Ariadne_Graph.test && test){
- test_print("Ariadne_Graph:: test messages on");
- }
- }
- private static void test_print(String message){
- if(test){
- System.out.println(message);
- }
- }
-
- // class data
- //
-
- // marks this class might put on a node
- public static Ariadne_TokenSet node_marks = new Ariadne_TokenSet(){{
- add(new Ariadne_Token("empty_root_label_list"));
- add(new Ariadne_Token("cycle_exists"));
- add(new Ariadne_Token("undefined_node_exists"));
- add(new Ariadne_Token("bad_descent_termination"));
- add(new Ariadne_Token("max_depth_reached"));
- }};
-
- // graph descend method return values
- private static Ariadne_TokenSet graph_descend_set = new Ariadne_TokenSet(){{
- add(new Ariadne_Token("empty_path_stack"));
- add(new Ariadne_Token("cycle_found"));
- add(new Ariadne_Token("undefined_node"));
- add(new Ariadne_Token("leaf"));
- add(new Ariadne_Token("max_depth_reached"));
- }};
-
-
- // instance data
-
- // constructors
- //
- public Ariadne_GraphDirectedAcyclic(){
- super(new HashMap<>(), null);
- }
-
- public Ariadne_GraphDirectedAcyclic(Map<Ariadne_Label, Ariadne_Node> node_map, Ariadne_DefinitionList recognizer_f_list, Ariadne_LabelList root_node_list, int max_depth, boolean verbose){
- super(node_map, recognizer_f_list);
- Ariadne_TokenSet cycle_detection_result = graph_mark_cycles(root_node_list, max_depth, verbose);
- }
-
- public Ariadne_GraphDirectedAcyclic(Map<Ariadne_Label, Ariadne_Node> node_map, Ariadne_DefinitionList recognizer_f_list, Ariadne_LabelList root_node_list){
- super(node_map, recognizer_f_list);
- Ariadne_TokenSet cycle_detection_result = graph_mark_cycles(root_node_list);
- }
-
- // interface functions
- //
- private List<Integer> path_find_cycle(Ariadne_LabelList path){
- if(path.size() <= 1) return null;
-
- int rightmost_index = path.size() - 1;
- Ariadne_Label rightmost_node_label = path.get(rightmost_index);
-
- int cycle_leftmost_index = path.indexOf(rightmost_node_label);
- Boolean has_cycle = cycle_leftmost_index < rightmost_index;
- if(!has_cycle) return null;
-
- List<Integer> result = new ArrayList<>();
- result.add(cycle_leftmost_index);
- result.add(rightmost_index);
- return result;
- }
-
- private boolean graph_descend_cycle_case(Ariadne_LabelList left_path, List<Ariadne_LabelList> path_stack, boolean verbose){
-
- List<Integer> cycle_index_interval = path_find_cycle(left_path);
- if(cycle_index_interval == null){
- return false;
- }
-
- int cycle_i0 = cycle_index_interval.get(0);
- int cycle_n = cycle_index_interval.get(1);
-
- if(verbose) Ariadne_Util.print_list(
- "Found cycle:",
- left_path.subList(cycle_i0, cycle_n + 1)
- );
-
- Ariadne_LabelList undefined_node_list = new Ariadne_LabelList();
- for (int i = cycle_i0; i <= cycle_n; i++){
- Ariadne_Label node_label = left_path.get(i);
- Ariadne_Node node = super.lookup(node_label);
- if(node != null){
- node.mark(new Ariadne_Token("cycle_member"));
- } else{
- undefined_node_list.add(node_label);
- }
- }
-
- if(verbose) Ariadne_Util.print_list(
- "Each undefined node could not be marked as a cycle member:",
- undefined_node_list
- );
-
- path_stack.subList(cycle_i0 + 1, cycle_n + 1).clear();
-
- return true;
- }
-
- private Ariadne_TokenSet graph_descend(List<Ariadne_LabelList> path_stack, int max_depth, boolean verbose){
- Ariadne_TokenSet ret_value = new Ariadne_TokenSet();
-
- if(path_stack.isEmpty()){
- ret_value.add(new Ariadne_Token("empty_path_stack"));
- return ret_value;
- }
-
- Ariadne_LabelList left_path = new Ariadne_LabelList();
- for (Ariadne_LabelList neighbor_list : path_stack){
- left_path.add(neighbor_list.get(0));
- }
-
- do{
-
- if(graph_descend_cycle_case(left_path, path_stack, verbose)){
- ret_value.add(new Ariadne_Token("cycle_found"));
- return ret_value;
- }
-
- Ariadne_Label it_node_label = path_stack.get(path_stack.size() - 1).get(0);
- Ariadne_Node it_node = super.lookup(it_node_label);
- if(it_node == null){
- ret_value.add(new Ariadne_Token("undefined_node"));
- return ret_value;
- }
-
- Ariadne_LabelList neighbor_list = it_node.neighbor_LabelList();
- if(neighbor_list.isEmpty()){
- ret_value.add(new Ariadne_Token("leaf"));
- return ret_value;
- }
-
- path_stack.add(new Ariadne_LabelList(neighbor_list));
- Ariadne_Label it_next_label = neighbor_list.get(0);
- left_path.add(it_next_label);
-
- if(max_depth > 0){
- max_depth--;
- if(max_depth == 0){
- if(verbose){
- Ariadne_Util.print_list("GraphDirectedAcyclic.GraphDescend:: max_depth reached, ending descent:", path_stack);
- }
- ret_value.add(new Ariadne_Token("max_depth_reached"));
- return ret_value;
- }
- }
-
- } while (true);
- }
-
-
- public Ariadne_TokenSet graph_mark_cycles(Ariadne_LabelList root_node_LabelList, int max_depth, boolean verbose){
- Ariadne_TokenSet ret_value = new Ariadne_TokenSet();
- boolean exists_malformed = false;
- Ariadne_TokenSet result;
-
- if(root_node_LabelList.isEmpty()){
- ret_value.add(new Ariadne_Token("empty_root_label_list"));
- return ret_value;
- }
-
- List<Ariadne_LabelList> path_stack = new ArrayList<>();
- path_stack.add(new Ariadne_LabelList(root_node_LabelList));
-
- do{
- result = graph_descend(path_stack, max_depth, verbose);
- if(result.contains(new Ariadne_Token("cycle_found"))) ret_value.add(new Ariadne_Token("cycle_exists"));
- if(result.contains(new Ariadne_Token("undefined_node"))) ret_value.add(new Ariadne_Token("undefined_node_exists"));
- if(result.contains(new Ariadne_Token("max_depth_reached"))) ret_value.add(new Ariadne_Token("max_depth_reached"));
- if(!result.contains(new Ariadne_Token("leaf")) && !result.contains(new Ariadne_Token("cycle_found"))) ret_value.add(new Ariadne_Token("bad_descent_termination"));
-
- Ariadne_LabelList top_list = path_stack.get(path_stack.size() - 1);
- top_list.remove(0);
- if(top_list.isEmpty()) path_stack.remove(path_stack.size() - 1);
-
- } while (!path_stack.isEmpty());
-
- if(verbose){
- if(ret_value.contains("bad_descent_termination")){
- System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: terminated with unexpected condition.");
- }
- if(ret_value.contains("cycle_exists")){
- System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: One or more cycles detected.");
- }
- if(ret_value.contains("undefined_node_exists")){
- System.out.println("GraphDirectedAcyclic.graph_mark_cycles:: Undefined nodes exist.");
- }
- }
-
- return ret_value;
- }
-
- public Ariadne_TokenSet graph_mark_cycles(Ariadne_LabelList root_node_LabelList){
- return graph_mark_cycles(root_node_LabelList, this.debug ? 40 : -1, this.debug);
- }
-
- @Override
- public Ariadne_Node lookup(Ariadne_Label node_label, boolean verbose){
- Ariadne_Node node = super.lookup(node_label, verbose);
- if(node != null && node.has_mark(new Ariadne_Token("cycle_member"))){
- if(verbose){
- System.out.println("GraphDirectedAcyclic.lookup:: Node is part of a cycle, not returned: " + node_label);
- }
- return null;
- }
- return node;
- }
-
- public Ariadne_Node lookup(Ariadne_Label node_label){
- return lookup(node_label, this.debug);
- }
-
-}
--- /dev/null
+/*
+SRTM_Depth is a list of neighbor SRTMs going down the leftmost side of
+a graph traversal. A leftmost traversal is one characterized by
+following leftmost not yet visited node on the most recently visited
+node's neighbor list.
+
+Depth traversal from a start node, ends when reaching a node that has
+no neighbors, or when reaching encountering a cycle.
+
+The `Node::neighbor()` function returns an SRTM for iterating over the
+node's neighbors. An SRTM is returned rather than a list, because in
+general a neighbor list is allowed to be unbounded. Though with a
+finite graph, that can not happen. (See IndexTree for an example of an
+infinite depth and infinite breadth graph traveral.)
+
+It is possible to construct and infinite graph such that the
+`SRTM_Depth::make()` function would never return.
+
+For a finite graph, this depth traversal will provably terminate, due
+to running out unique (non cycle) nodes to visit. More generally, if
+graph traversal from a start node is guaranteed to reach a leaf node
+(has no neighbors), or a a cycle, within a finite number of node
+traversal steps, then `SRTM_Depth::make()` will always return.
+
+Each call to step causes the TM read head to move to the next lowest
+depth, leftmost unvisited node. This might require backtracking and
+descending again.
+
+Nodes are referenced by label.
+
+A null valued label is flagged as an error, though we still look it up
+in the graph. It is a fatal error, `exit(1)` if `lookup` returns a
+null node.
+
+*/
+
+import com.ReasoningTechnology.Ariadne.Ariadne_SRTM;
+import com.ReasoningTechnology.Ariadne.Ariadne_Graph;
+
+
+class SRTM_Depth{
+
+ // static
+ //
+
+ PathStack make(Graph g){
+ return new SRTM_Depth(g);
+ }
+
+ // instance data
+ //
+ protected List<Ariadne_SRTM> path;
+ protected Graph graph;
+
+ // constructor
+ //
+ protected SRTM_Depth(Graph g){
+ set_topography(topo_null);
+ if(g == null) return;
+ graph = g;
+ path.add( g.start() );
+ descend();
+ }
+
+ // instance interface implementation
+ //
+
+
+ // A path is terminated by a leaf node or discovering a cycle.
+ protected boolean extend_path_to_termination(){
+
+ ArrayList<Label> = path new ArrayList<>;
+
+
+ // Get the label for current child of the deepest in tree child_srtm
+ // The current child is the one under the read head.
+ Ariadne_SRTM<Ariadne_SRTM> child_srtm = path.get(path.size() - 1);
+ Ariande_Label label = child_srtm.read();
+ if( label == null ){
+ System.out.println("SRTM_Depth::extend_to_leaf found null node");
+ }
+
+ // check if label has been visited before:
+ //
+
+
+ // descend from the label and put it in to
+ Ariadne_Node node = graph.lookup(label);
+ if( node == null ){
+ System.out.println
+ (
+ "SRTM_Depth::descend error: label(\""
+ + label
+ + "\") not found in graph."
+ );
+ return false;
+ }
+
+ Ariadne_SRTM_Label = node.neighbor();
+
+ if( !
+
+ Ariadne_SRTM<Ariadne_SRTM> srtm = Ariadna_SRTM_List.make(path);
+ if( !srtm.can_read() ) return;
+ do{
+ child_srtm = srtm.read();
+ if( !srtm.can_step() ) break;
+ srtm.step();
+ }while(true);
+
+ visited.push(path.
+ }
+
+ // being a good object citizen
+ //
+
+
+}
// Static
//
- public static SRTM_Child make( Label first_child_label ){
- return new SRTM_Child( first_child_label );
+ public static SRTM_Child make( Label leftmost_child_label ){
+ return new SRTM_Child( leftmost_child_label );
}
// Instance data
This implementation is nearly ready, to be included in the Ariadne
library for generalized diagonal traversal. I have abstracted out all
references to the IndexTree. It still needs to remove child lists that
-have been completely reversed from the child_strm_list. This was not
+have been completely reversed from the child_srtm_list. This was not
needed for the IndexTree because it is infinite, so they will never be
completely traversed. Also needed, is to stop when a node does not
have a child list. Again, this is not needed here because the
List<Label> diagonal_1 = new ArrayList<>();
- // inc_down from each node on diagonal_0 -> entry on child_strm list
+ // inc_down from each node on diagonal_0 -> entry on child_srtm list
Ariadne_SRTM_List<Label> diagonal_srtm = Ariadne_SRTM_List.make(diagonal);
if( diagonal_srtm.can_read() ){
do{
}while(true);
}
- // add to diagonal_1 from each on entry on the child_strm list
+ // add to diagonal_1 from each on entry on the child_srtm list
Ariadne_SRTM_List<SRTM_Child> child_srtm_srtm = Ariadne_SRTM_List.make(child_srtm_list);
if( child_srtm_srtm.can_read() ){
do{
boolean is_null();
Ariadne_Label copy();
@Override String toString();
+ @Override public boolean equals(Object o);
}