check in to support minor release of the GraphIndexTree example examples_1.0
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Fri, 31 Jan 2025 10:12:02 +0000 (10:12 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Fri, 31 Jan 2025 10:12:02 +0000 (10:12 +0000)
14 files changed:
developer/bash/Build [deleted file]
developer/deprecated/TM_SR_ND_Depth_initialize.java [new file with mode: 0644]
developer/documentđź–‰/bugs.txt
developer/example/GraphCycleCFinder/TM_SR_ND_Depth.java [deleted file]
developer/example/GraphIndexTree/Graph.java
developer/javacđź–‰/Ariadne_ContextPath_FD.java [deleted file]
developer/javacđź–‰/Ariadne_ContextStack.xjava [new file with mode: 0644]
developer/javacđź–‰/Ariadne_Graph.java
developer/javacđź–‰/Ariadne_Graph_FD.java
developer/javacđź–‰/Ariadne_Node.java
developer/javacđź–‰/Ariadne_Node_FD.java
developer/javacđź–‰/Ariadne_Node_Set.java [new file with mode: 0644]
developer/javacđź–‰/Ariadne_TM_SR_ND_Depth.xjava [new file with mode: 0644]
developer/javacđź–‰/Ariadne_TM_SR_NX_Set.java

diff --git a/developer/bash/Build b/developer/bash/Build
deleted file mode 100755 (executable)
index 2a18026..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-java com.ReasoningTechnology."Ariadne".Build
diff --git a/developer/deprecated/TM_SR_ND_Depth_initialize.java b/developer/deprecated/TM_SR_ND_Depth_initialize.java
new file mode 100644 (file)
index 0000000..0dcb244
--- /dev/null
@@ -0,0 +1,57 @@
+  // Given a context_path_tm and path_member_set.
+  // Initializes the path_member_set. Leaves head on last cell of context_path_tm.
+  // Returns a successful initlaization flag and possibly not null cycle_node_label
+  public class initialize{
+    static public initialize f(context_path_tm ,path_member_set){
+      initialize instance = new initialize();
+      instance.g(context_path_tm ,path_member_set);
+      return instance;
+    }
+    public Label first_in_path_cycle_node_label = null;
+    public boolean success = false;
+
+    protected void g(context_path_tm ,path_member_set){
+
+      if( context_path.isEmpty() ){
+        System.out.println("TM_SR_NX_Depth::initialize required context_path is empty.");
+        success = false;
+        return;
+      }
+
+      boolean is_cycle_node = false;
+      Ariadne_TM_SR_NX sibling_tm = null;
+      Ariadne_Label path_node_label = null;
+
+      do{
+        sibling_tm = context_path_tm.read();
+        path_node_label = sibling_tm.read();
+        if(path_node_label == null){
+          System.out.println("TM_SR_NX_Depth::complete_context_path hit null path label on path");
+          success = false;
+          return;
+        }
+
+        is_cycle_node = path_member_set.contains(path_node_label);
+        if( is_cycle_node ) break;
+
+        path_member_set.add( path_node_label );
+
+        if( !context_path_tm.can_step() ) break;
+        context_path_tm.step();
+
+      }while(true);
+
+      if( is_cycle_node && context_path_tm.can_step() ){
+        System.out.println
+          (
+           "TM_SR_NX_Depth::initialize_path_member_set: cycle found in initial context_path."
+           );
+        first_in_path_cycle_node_label = path_node_label;
+        success = false;
+        return;
+      }
+
+      success = true;
+      return;
+    }
+  }
index b4971df..2b975f7 100644 (file)
 2025-01-24T10:54:26Z[]
     global substitute in this file _ND -> _NX
 
+2025-01-26T15:35:15Z[]
+
+    Chat GPT explaining why Java is giving a type mismatch error on two identical types.
+    Of course we should give Java a break, as it is a young experimental language.
+
+      Yes, you're absolutely right! The generic bounds at the top of the class declaration guarantee that both GraphType and SiblingContext are tied to the same LabelType. Specifically:
+
+      SiblingContext extends Ariadne_TM_SR_NX_F<LabelType> ensures that SiblingContext is a subtype of Ariadne_TM_SR_NX_F<LabelType>.
+      GraphType extends Ariadne_Graph_FD<LabelType, NodeType> ensures that GraphType is a type of graph using the same LabelType.
+      Thus, conceptually, the cast should always be safe because graph.start() returns a type that satisfies the bounds of SiblingContext. The problem is that Java's type system is not sophisticated enough to understand this guarantee at runtime.
+
+
+     ```
+     public class 
+       Ariadne_Graph_FD
+       < LabelType extends Ariadne_Label ,NodeType extends Ariadne_Node_FD<LabelType> > 
+       extends Ariadne_Graph<LabelType ,NodeType>
+     {
+      ...
+        @Override public Ariadne_TM_SR_NX_F<LabelType> start(){
+          return Ariadne_TM_SR_NX_Array.make(start_list);
+        }
+
+    ```
+
+    ```
+    public class Ariadne_ContextStack
+      <
+        LabelType extends Ariadne_Label
+        ,NodeType extends Ariadne_Node_FD<LabelType>
+        ,SiblingContext extends Ariadne_TM_SR_NX_F<LabelType>
+        ,GraphType extends Ariadne_Graph_FD<LabelType, NodeType>
+      >
+    {
+      ...
+      protected Ariadne_ContextStack(GraphType graph){
+        this.graph = graph;
+        this.context_path = new ArrayList<>();
+        this.context_path.add( graph.start() ); // <--- type mismatch error this line
+        this.path_member_set = new HashSet<>();
+      }
+      
+      ...
+
+      private final List<SiblingContext> context_path;
+
+    ```
+
+    Sure looks to me like graph.start() is said to return the same Ariadne_TM_SR_NX_F<LabelType>, as that accepted by context_path.add(). The two
+    'LabelType' are tied together at the top of the class ContextStack declaration.
+    However the compiler says:
+
+   ```
+    javacđź–‰/Ariadne_ContextStack.java:72: error: incompatible types: Ariadne_TM_SR_NX_F<LabelType> cannot be converted to SiblingContext
+        this.context_path.add( graph.start() );
+                                          ^
+      where LabelType,SiblingContext are type-variables:
+        LabelType extends Ariadne_Label declared in class Ariadne_ContextStack
+        SiblingContext extends Ariadne_TM_SR_NX_F<LabelType> declared in class Ariadne_ContextStack
+   ```
+
+   This is only one of many type errors that appear to be the same sort of thins.
+   It is a scary proposition to be start correcting the compiler and inserting
+   a bunch of casts.  And which of these casts would be a mistake?
+
+   small variation:
+
+   ```
+  javacđź–‰/Ariadne_ContextStack.java:74: error: incompatible types: Ariadne_TM_SR_NX_F<LabelType> cannot be converted to SiblingContext
+      SiblingContext s = t;
+   ```
+
+   add insult to injury, it gives a syntax error when a cast is added:
+   ```
+       this.context_path.add( (SiblingContext)graph.start() );
+   ```
+   ```
+     javacđź–‰/Ariadne_ContextStack.java:77: error: illegal start of type
+      this.context_path.add( (SiblingContext)graph.start() );
+      ^
+   ```
+
+   I thought I was going to be doing graph research, instead I am using
+   my time to learn the quirks of Java. Is it a more valuable activity?
+
+   This works, but issues a warning, which can be surpressed. Great, a
+   language made to patch the main language. Very useful of the main
+   language needs patching:
+
+   ```
+    @SuppressWarnings("unchecked")
+    SiblingContext sc = (SiblingContext) graph.start();
+    this.context_path.add( sc );
+   ```
+
+2025-01-31T07:43:30Z[]
+
+  Suppose class A parent, class B child type. Java does not allow
+  class B to have static methods with the same type signature as
+  static methods in class A.
+
+  This clobbers the factory method pattern because the factory is
+  always called `make`.  
+
+  The 'cure' is to require each class to have a unique factory
+  method name.  Perhaps make_<type>.  So basically like a constructor
+  with 'make_' prepended.  However, statics are already called
+  with their type name, so then a call to make would look like:
+
+     T x = T.make_T();
+
+  Type names tend to be long in Java and there is no type
+  alias facility, so that will surely span more than one line.
+
+  How many times can a person write type the same thing without
+  making an error?  It is a game of 'Simon Says'.
+
+
diff --git a/developer/example/GraphCycleCFinder/TM_SR_ND_Depth.java b/developer/example/GraphCycleCFinder/TM_SR_ND_Depth.java
deleted file mode 100644 (file)
index ca02b2b..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
-
-Each member of a `path` list is a node label. A path is created by traversing the graph.
-
-Imagine expanding each member of a path into a sibling list tm, with the cell under
-the head being the label on the path.  This is the context_path.
-
-Because a context path holds the siblings, it can be used as the state variable during
-a tree traversal.
-
-*/
-
-import java.util.HashSet;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.ReasoningTechnology.Ariadne.Ariadne_TM_SR_NX;
-import com.ReasoningTechnology.Ariadne.Ariadne_Graph;
-import com.ReasoningTechnology.Ariadne.Ariadne_Node;
-import com.ReasoningTechnology.Ariadne.Ariadne_Label;
-import com.ReasoningTechnology.Ariadne.Ariadne_TM_SR_NX_Array;
-import com.ReasoningTechnology.Ariadne.Ariadne_TM_SR_NX_List;
-
-class TM_SR_NX_Depth extends Ariadne_TM_SR_NX<Label>{
-
-  // ----------------------------------------
-  // static
-  //
-
-  TM_SR_NX_Depth make(Ariadne_Graph graph){
-    if(graph == null) return null;
-    TM_SR_NX_Depth depth = new TM_SR_NX_Depth();
-    depth.graph = graph;
-    depth.context_path.add( graph.start() );
-    depth.context_path_tm = Ariadne_TM_SR_NX_Array.make(context_path);
-    initialize i = initialize.f(depth.context_path_tm ,depth.path_member_set);
-    if( !i.success() ) return null;
-    first_in_path_cycle_node_label = i.first_in_path_cycle_node_label;
-    return depth;
-  }
-
-  // ----------------------------------------
-  // instance data
-  //
-
-  protected Graph graph = null;
-  protected List<Ariadne_TM_SR_NX<Label>> context_path = new ArrayList<>();
-  protected Ariadne_TM_SR_NX_Array<Ariadne_TM_SR_NX> context_path_tm = null;
-  protected Label first_in_path_cycle_node_label = null;
-
-  // Used for cycle detection.
-  HashSet<Ariadne_Label> path_member_set = new HashSet<>();
-
-  // ----------------------------------------
-  // constructor
-  //
-
-  protected TM_SR_NX_Depth(){
-    set_topology(topo_null);
-  }
-
-
-  // ----------------------------------------
-  // instance interface implementation
-  //
-
-  // Given a context_path_tm and path_member_set.
-  // Initializes the path_member_set. Leaves head on last cell of context_path_tm.
-  // Returns a successful initlaization flag and possibly not null cycle_node_label
-  public class initialize{
-    static public initialize f(context_path_tm ,path_member_set){
-      initialize instance = new initialize();
-      instance.g(context_path_tm ,path_member_set);
-      return instance;
-    }
-    public Label first_in_path_cycle_node_label = null;
-    public boolean success = false;
-
-    protected void g(context_path_tm ,path_member_set){
-
-      if( context_path.isEmpty() ){
-        System.out.println("TM_SR_NX_Depth::initialize required context_path is empty.");
-        success = false;
-        return;
-      }
-
-      boolean is_cycle_node = false;
-      Ariadne_TM_SR_NX sibling_tm = null;
-      Ariadne_Label path_node_label = null;
-
-      do{
-        sibling_tm = context_path_tm.read();
-        path_node_label = sibling_tm.read();
-        if(path_node_label == null){
-          System.out.println("TM_SR_NX_Depth::complete_context_path hit null path label on path");
-          success = false;
-          return;
-        }
-
-        is_cycle_node = path_member_set.contains(path_node_label);
-        if( is_cycle_node ) break;
-
-        path_member_set.add( path_node_label );
-
-        if( !context_path_tm.can_step() ) break;
-        context_path_tm.step();
-
-      }while(true);
-
-      if( is_cycle_node && context_path_tm.can_step() ){
-        System.out.println
-          (
-           "TM_SR_NX_Depth::initialize_path_member_set: cycle found in initial context_path."
-           );
-        first_in_path_cycle_node_label = path_node_label;
-        success = false;
-        return;
-      }
-
-      success = true;
-      return;
-    }
-  }
-
-  public boolean path_has_cycle(){
-    return first_in_path_cycle_node_label != null;
-  }
-
-  
-  // Upon stepping on a cycle node, we must go back and pick the next start node.
-  // The context path that stepped on the cycle node is saved to document the cycle.
-  // A path is terminated by a cycle being found, or a leaf node, or all the children having been visited. The terminating node (label) becomes the read value. Upon entering `step()`
-  // the head is on the prior leaf node.
-  public void step(){
-
-    boolean is_cycle_node = false;
-    Ariadne_Node path_node = null;
-    boolean is_leaf_node = false;
-    Ariadne_TM_SR_NX sibling_tm = null;
-    Ariadne_Label path_node_label = null;
-
-    sibling_tm = context_path_tm.read();
-    path_node_label = sibling_tm.read();
-
-    do{
-      path_node = graph.node(path_node_label);
-      if(path_node == null){
-        System.out.println
-          (
-           "TM_SR_NX_Depth::complete_context_path internal algorithm error, node on path not found in graph for: label(\""
-           + path_node_label
-           + "\")"
-           );
-        return false;
-      }
-
-      // attempt to extend downward
-      sibling_tm = path_node.neighbor();
-      is_leaf_node = sibling_tm == null || !sibling_tm.can_read();
-      if(is_leaf_node){ 
-
-      // add the sibling_tm to the context_path
-      context_path.add(sibling_tm);
-
-      // exit if path_node cycles back
-      path_node_label = sibling_tm.read();
-      is_cycle_node = path_member_set.contains(path_node_label);
-      if( is_cycle_node ){
-        // caller needs to check for cycle found before each new step
-        first_in_path_cycle_node_label = path_node_label;
-        return true; 
-      }
-
-      // path_node_label has now been visited
-      path_member_set.add(path_node_label);
-
-    }while(true);
-  }
-
-  // being a good object citizen
-  //
-
-
-}
index 67c887e..0de9fef 100644 (file)
@@ -1,8 +1,8 @@
 import com.ReasoningTechnology.Ariadne.Ariadne_Label;
 import com.ReasoningTechnology.Ariadne.Ariadne_Node;
-import com.ReasoningTechnology.Ariadne.Ariadne_Graph_FD;
+import com.ReasoningTechnology.Ariadne.Ariadne_Graph;
 
-public class Graph extends Ariadne_Graph_FD<Label ,Node>{
+public class Graph extends Ariadne_Graph<Label ,Node>{
 
   @SuppressWarnings("unchecked")
   public static Graph make(){
diff --git a/developer/javacđź–‰/Ariadne_ContextPath_FD.java b/developer/javacđź–‰/Ariadne_ContextPath_FD.java
deleted file mode 100644 (file)
index 215072e..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-package com.ReasoningTechnology.Ariadne;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
-// SiblingContext a tm of graph node labels, that are siblings to a path node, in a tree search
-// LT == Label Type
-public class Ariadne_ContextPath_FD
-  <
-    SiblingContext extends Ariadne_TM_SR_NX<LT> 
-    ,LT extends Ariadne_Label
-    >
-{
-
-  //----------------------------------------
-  // Static
-
-  public static
-    <
-     SiblingContext extends Ariadne_TM_SR_NX<LT> 
-     ,LT extends Ariadne_Label
-     >
-    Ariadne_ContextPath_FD<SiblingContext ,LT> 
-    make()
-  {
-    return new Ariadne_ContextPath_FD<>();
-  }
-
-  public static
-    <
-     SiblingContext extends Ariadne_TM_SR_NX<LT> 
-     ,LT extends Ariadne_Label
-     >
-    Ariadne_ContextPath_FD<SiblingContext ,LT> 
-    make(Ariadne_ContextPath_FD<SiblingContext ,LT> other)
- {
-    return new Ariadne_ContextPath_FD<>();
-  }
-
-
-  //----------------------------------------
-  // Instance data
-
-  private final List<SiblingContext> context_path_list;
-  private final HashSet<LT> path_member_set;
-  private LT cycle_node_label;
-
-  //----------------------------------------
-  // Constructors
-
-  public Ariadne_ContextPath_FD(){
-    this.context_path_list = new ArrayList<>();
-    this.path_member_set = new HashSet<>();
-  }
-
-  public Ariadne_ContextPath_FD(Ariadne_ContextPath_FD<SiblingContext ,LT> other){
-    this.context_path_list = new ArrayList<>( other.context_path_list );
-    this.path_member_set = new HashSet<>( other.path_member_set );
-  }
-
-  //----------------------------------------
-  // Instance methods
-
-  /**
-   * Adds a traversal state to the context path.
-   *
-   * @param sibling_context The traversal state to add.
-   * @return true if successfully added, false if it introduces a cycle.
-   */
-  public boolean push(SiblingContext sibling_context){
-    if( sibling_context == null || !sibling_context.can_read() ){
-      return false;
-    }
-
-    LT label = sibling_context.read();
-    if( path_member_set.contains(label) ){
-      cycle_node_label = label;
-      return false; // Cycle detected
-    }
-
-    context_path_list.add( sibling_context );
-    path_member_set.add(label);
-    return true;
-  }
-
-  /**
-   * Removes the last traversal state from the context path.
-   *
-   * @return The removed traversal state, or null if the path is empty.
-   */
-  public SiblingContext pop(){
-    if( context_path_list.isEmpty() ){
-      return null;
-    }
-
-    SiblingContext last = context_path_list.remove( context_path_list.size() - 1 );
-    path_member_set.remove( last.read() );
-    return last;
-  }
-
-  /**
-   * Checks if the context path contains the given label.
-   *
-   * @param label The label to check.
-   * @return true if the label is in the path, false otherwise.
-   */
-  public boolean contains(LT label){
-    return path_member_set.contains(label);
-  }
-
-  /**
-   * Returns the size of the context path.
-   *
-   * @return The number of traversal states in the path.
-   */
-  public int size(){
-    return context_path_list.size();
-  }
-
-  /**
-   * Provides a string representation of the context path for debugging.
-   *
-   * @return A string representing the context path.
-   */
-  @Override
-  public String toString(){
-    StringBuilder output = new StringBuilder("Ariadne_ContextPath_FD(");
-    Ariadne_TM_SR_NX_F< SiblingContext > tm = Ariadne_TM_SR_NX_Array.make(context_path_list);
-    if( tm.can_read() ){
-      do{
-        output.append("Sibling( ");
-        output.append( tm.toString() );
-        output.append(" )");
-        if( !tm.can_step() ) break;
-        tm.step();
-        output.append(" ,");
-      }while(true);
-    }
-    output.append(")");
-    return output.toString();
-  }
-
-}
-
diff --git a/developer/javacđź–‰/Ariadne_ContextStack.xjava b/developer/javacđź–‰/Ariadne_ContextStack.xjava
new file mode 100644 (file)
index 0000000..a903858
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+  Node.neighbor() returns a tm full of labels to neighbor nodes. For a node in a tree neighbors are called 'siblings'.
+
+  Each path node (node in a traversal path) comes from either the start list, or a neighbor list.  This is the path node's 'sibling context'.
+
+  The sibling context is important in both breadth first and depth first traversals.
+
+  When the context for each node along a path is put on a stack, the result is the ContextStack.
+
+*/
+
+package com.ReasoningTechnology.Ariadne;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+public class Ariadne_ContextStack
+  <
+    Label extends Ariadne_Label
+    ,Node extends Ariadne_Node_FD<Label>
+    ,SiblingContext extends Ariadne_TM_SR_NX_F<Label>
+  >
+{
+
+  //----------------------------------------
+  // Static
+
+  public static
+    <
+      Label extends Ariadne_Label
+      ,Node extends Ariadne_Node_FD<Label>
+      ,SiblingContext extends Ariadne_TM_SR_NX_F<Label>
+    >
+    Ariadne_ContextStack<Label ,Node ,SiblingContext>
+    make()
+  {
+    return new Ariadne_ContextStack<>();
+  }
+
+  public static
+    <
+      Label extends Ariadne_Label
+      ,Node extends Ariadne_Node_FD<Label>
+      ,SiblingContext extends Ariadne_TM_SR_NX_F<Label>
+      ,Graph extends Ariadne_Graph_FD<Label, Node>
+    >
+    Ariadne_ContextStack<Label ,Node ,SiblingContext>
+    make(Ariadne_ContextStack<Label ,Node ,SiblingContext> other)
+ {
+    // full form required by the compiler
+    return new Ariadne_ContextStack<Label, Node, SiblingContext, Graph>(other);
+  }
+
+
+  //----------------------------------------
+  // Instance data
+
+  private final List<SiblingContext> context_stack;
+  private final HashSet<Label> path_member_set; // speed up cycle checks
+  private Label cycle_node_label;
+
+  //----------------------------------------
+  // Constructors
+
+  protected Ariadne_ContextStack(){
+    this.context_stack = new ArrayList<>();
+    this.path_member_set = new HashSet<>();
+  }
+
+  protected Ariadne_ContextStack(
+    Ariadne_ContextStack<Label ,Node ,SiblingContext> other
+  ){
+    this.context_stack = new ArrayList<>( other.context_stack );
+    this.path_member_set = new HashSet<>( other.path_member_set );
+  }
+
+  //----------------------------------------
+  // Instance methods
+
+  public enum PushResult{
+    NO_CONTEXT
+    ,CYCLE
+    ,SUCCESS
+  }
+  public boolean push(SiblingContext sibling_context){
+    if( sibling_context == null || !sibling_context.can_read() ){
+      return PushResult.NO_CONTEXT;
+    }
+
+    Label label = sibling_context.read();
+    if( path_member_set.contains(label) ){
+      cycle_node_label = label;
+      return PushResult.CYCLE;
+    }
+
+    context_stack.add( sibling_context );
+    path_member_set.add(label);
+    return PushResult.SUCCESS;
+  }
+
+  public SiblingContext top(){
+    return context_stack.get( context_stack.size() - 1 );
+  }
+
+  public SiblingContext pop(){
+    if( context_stack.isEmpty() ){
+      return null;
+    }
+    SiblingContext popped_top = context_stack.remove( context_stack.size() - 1 );
+    path_member_set.remove( popped_top.read() );
+    return popped_top;
+  }
+
+  public boolean in_path(Label label){
+    return path_member_set.contains(label);
+  }
+
+  /**
+   * Checks if the context path contains the given label.
+   *
+   * @param label The label to check.
+   * @return true if the label is in the path, false otherwise.
+   */
+  public boolean contains(Label label){
+    return path_member_set.contains(label);
+  }
+
+  /**
+   * Returns the size of the context path.
+   *
+   * @return The number of traversal states in the path.
+   */
+  public int size(){
+    return context_stack.size();
+  }
+
+  public enum StepResult{
+    NOT_CANSTEP
+    ,CYCLE
+    ,SUCCESS
+  }
+  StepResult top_step(){
+    if( top() == null || !top().can_step() ) return StepResult.NOT_CANSTEP;
+    top().step();
+    Label node_label = top().read();
+    if( path_member_set.contains(node_label) ){ // cycle found
+      cycle_node_label = node_label;
+      return StepResult.CYCLE;
+    }
+    path_member_set.add(node_label);
+    context_stack.push(s); 
+    return StepResult.SUCCESS;
+  }
+  
+  //----------------------------------------
+  // Good Citizen
+
+  @Override public boolean isEmpty(){
+    return context_stack.isEmpty();
+  }
+
+  /**
+   * Provides a string representation of the context path for debugging.
+   *
+   * @return A string representing the context path.
+   */
+  @Override public String toString(){
+    StringBuilder output = new StringBuilder("Ariadne_ContextStack(");
+    Ariadne_TM_SR_NX_F< SiblingContext > tm = Ariadne_TM_SR_NX_Array.make(context_stack);
+    if( tm.can_read() ){
+      do{
+        output.append("Sibling( ");
+        output.append( tm.toString() );
+        output.append(" )");
+        if( !tm.can_step() ) break;
+        tm.step();
+        output.append(" ,");
+      }while(true);
+    }
+    output.append(")");
+    return output.toString();
+  }
+
+}
+
index 3fe2e00..6ea7e43 100644 (file)
@@ -32,11 +32,15 @@ public class Ariadne_Graph<LT extends Ariadne_Label, NT extends Ariadne_Node<LT>
     ,UNKNOWN
   }
 
-  public static < T extends Ariadne_Label, N extends Ariadne_Node<T> > Ariadne_Graph<T, N> make() {
+  public static 
+  < T extends Ariadne_Label, N extends Ariadne_Node<T> > 
+  Ariadne_Graph<T, N> make() {
     return new Ariadne_Graph<>();
   }
 
-  public static <T extends Ariadne_Label, N extends Ariadne_Node<T>> Ariadne_Graph<T, N> make(String name) {
+  public static 
+  <T extends Ariadne_Label, N extends Ariadne_Node<T>> 
+  Ariadne_Graph<T, N> make(String name) {
     return new Ariadne_Graph<>(name);
   }
 
index 28783df..e225699 100644 (file)
@@ -9,26 +9,47 @@ package com.ReasoningTechnology.Ariadne;
 import java.util.ArrayList;
 import java.util.HashMap;
 
-// LT == Label Type, NT == Node Type
-public class Ariadne_Graph_FD<LT extends Ariadne_Label ,NT extends Ariadne_Node<LT>> extends Ariadne_Graph<LT ,NT>{
+public class Ariadne_Graph_FD
+  < 
+    LabelType extends Ariadne_Label 
+    ,NodeType extends Ariadne_Node_FD<LabelType> 
+  > 
+  extends Ariadne_Graph<LabelType ,NodeType>
+{
 
   // Static
   //
 
-  public static <T extends Ariadne_Label ,N extends Ariadne_Node<T>> Ariadne_Graph_FD<T ,N> make(){
+  // Java does not allow 'make' in the type extended from a type that has 'make',
+  // so these become 'make_FD'. Why? Because it is a game of Simon Says, and
+  // I got caught here, I didn't add the _FD initially.
+
+  public static 
+  < T extends Ariadne_Label ,N extends Ariadne_Node_FD<T> > 
+  Ariadne_Graph_FD<T ,N> make_FD(){
     return new Ariadne_Graph_FD<>();
   }
 
-  public static <T extends Ariadne_Label ,N extends Ariadne_Node<T>> Ariadne_Graph_FD<T ,N> make(String name){
+  public static 
+  < T extends Ariadne_Label ,N extends Ariadne_Node_FD<T> > 
+  Ariadne_Graph_FD<T ,N> make_FD(String name){
     return new Ariadne_Graph_FD<>(name);
   }
 
   // Instance data
   //
 
-  private final HashMap<LT ,NT> node_db = new HashMap<>();
-  private final HashMap< Ariadne_Pair<LT ,LT> ,Ariadne_Edge<LT> > edge_db = new HashMap<>();
-  private final ArrayList<LT> start_list = new ArrayList<>();
+  private final 
+  HashMap<LabelType ,NodeType> 
+  node_db = new HashMap<>();
+
+  private final 
+  HashMap< Ariadne_Pair<LabelType ,LabelType> ,Ariadne_Edge<LabelType> > 
+  edge_db = new HashMap<>();
+
+  private final 
+  ArrayList<LabelType> 
+  start_list = new ArrayList<>();
 
   // Constructor(s)
   //
@@ -51,7 +72,7 @@ public class Ariadne_Graph_FD<LT extends Ariadne_Label ,NT extends Ariadne_Node<
     // Nodes are distinct due to the use of the HashMap
 
     // Check that start nodes are in the graph
-    Ariadne_TM_SR_NX_Array<LT> tm = Ariadne_TM_SR_NX_Array.make(start_list);
+    Ariadne_TM_SR_NX_Array<LabelType> tm = Ariadne_TM_SR_NX_Array.make(start_list);
     if( tm.can_read() ){
       do{
         start_flag = this.node( tm.read() ) != null;
@@ -64,27 +85,27 @@ public class Ariadne_Graph_FD<LT extends Ariadne_Label ,NT extends Ariadne_Node<
     return distinct_flag && start_flag;
   }
 
-  @Override public Ariadne_TM_SR_NX<LT> start(){
+  @Override public Ariadne_TM_SR_NX_F<LabelType> start(){
     return Ariadne_TM_SR_NX_Array.make(start_list);
   }
 
   // Lookup a node on the graph by label
-  @Override public NT node(LT label){
+  @Override public NodeType node(LabelType label){
     return node_db.get(label);
   }
 
   // A tm of all nodes
-  public Ariadne_TM_SR_NX<NT> node(){
+  public Ariadne_TM_SR_NX_F<NodeType> node(){
     return Ariadne_TM_SR_NX_Array.make( new ArrayList<>(node_db.values()) );
   }
 
   // Lookup an edge by two labels. For a directed graph, label0 is the origin node label.
-  @Override public Ariadne_Edge<LT> edge(LT label0 ,LT label1){
+  @Override public Ariadne_Edge<LabelType> edge(LabelType label0 ,LabelType label1){
     return edge_db.get( Ariadne_Pair.make(label0 ,label1) );
   }
 
   // A tm of all edges
-  public Ariadne_TM_SR_NX<Ariadne_Edge<LT>> edge(){
+  public Ariadne_TM_SR_NX_F<Ariadne_Edge<LabelType>> edge(){
     return Ariadne_TM_SR_NX_Array.make( new ArrayList<>(edge_db.values()) );
   }
 
@@ -96,7 +117,7 @@ public class Ariadne_Graph_FD<LT extends Ariadne_Label ,NT extends Ariadne_Node<
     output.append("Graph_FD( ");
 
     {
-      Ariadne_TM_SR_NX<NT> tm = this.node();
+      Ariadne_TM_SR_NX_F<NodeType> tm = this.node();
       if( !tm.can_read() ){
         output.append( "Node_list()" );
       }else{
@@ -107,7 +128,7 @@ public class Ariadne_Graph_FD<LT extends Ariadne_Label ,NT extends Ariadne_Node<
     }
 
     {
-      Ariadne_TM_SR_NX<Ariadne_Edge<LT>> tm = this.edge();
+      Ariadne_TM_SR_NX_F<Ariadne_Edge<LabelType>> tm = this.edge();
       if( !tm.can_read() ){
         output.append( "Edge_list()" );
       }else{
index 7cd8bac..347489d 100644 (file)
@@ -2,6 +2,8 @@
 A Node potentially has an infinite number of neighbors, in which case its
 neighbor set is defined using a function. See the IndexTree example.
 
+A node extends from HashMap so to facilitate the user in adding his or
+her own properties.
 
 
 */
@@ -17,7 +19,9 @@ public class Ariadne_Node<LT extends Ariadne_Label> extends HashMap<String ,Obje
   // Owned by the class
   //
 
-  public static <T extends Ariadne_Label> Ariadne_Node<T> make(T label){
+  public static 
+  <T extends Ariadne_Label> 
+  Ariadne_Node<T> make(T label){
     return new Ariadne_Node<>(label);
   }
 
@@ -42,6 +46,7 @@ public class Ariadne_Node<LT extends Ariadne_Label> extends HashMap<String ,Obje
     return this.label;
   }
 
+  // the returned machine should have the head on leftmost
   public Ariadne_TM_SR_NX<LT> neighbor(){
     throw new UnsupportedOperationException("Ariadne_Node::neighbor not implemented in the base class.");
   }
index 4decffc..9ef66fb 100644 (file)
@@ -1,13 +1,13 @@
 /*
 A node with a finite fixed set of neighbors.
 
-
 */
 
 package com.ReasoningTechnology.Ariadne;
 
 import java.util.HashSet;
 import java.util.Arrays;
+import java.util.List;
 
 // LT == Label Type
 public class Ariadne_Node_FD<LT extends Ariadne_Label> extends Ariadne_Node<LT>{
@@ -15,41 +15,31 @@ public class Ariadne_Node_FD<LT extends Ariadne_Label> extends Ariadne_Node<LT>{
   // Owned by the class
   //
 
-  @SafeVarargs
-  public static <T extends Ariadne_Label> Ariadne_Node_FD<T> make(T label ,T... neighbors){
-    return new Ariadne_Node_FD<>(label ,neighbors);
-  }
-
   // Data owned by the instance
   //
 
-  private final HashSet<LT> neighbor_set;
-
   // Constructors
   // 
 
-  @SafeVarargs
-  protected Ariadne_Node_FD(LT label ,LT... neighbors){
+  protected Ariadne_Node_FD(LT label){
     super(label);
-    this.neighbor_set = new HashSet<>();
-    if( neighbors != null ){
-      this.neighbor_set.addAll(Arrays.asList(neighbors));
-    }
   }
 
   // Instance interface
   //
   
-  @Override public Ariadne_TM_SR_NX<LT> neighbor(){
-    return Ariadne_TM_SR_NX_Set.make(neighbor_set);
+  @Override public Ariadne_TM_SR_NX_F<LT> neighbor(){
+    throw new UnsupportedOperationException("Ariadne_Node_F::neighbor not implemented in the base class.");
   }
 
   // Good citizen
   //
 
   @Override public String toString(){
-    Ariadne_TM_SR_NX_Set<LT> tm = Ariadne_TM_SR_NX_Set.make(neighbor_set);
+
     boolean has_label = label() != null;
+
+    Ariadne_TM_SR_NX_F<LT> tm = neighbor();
     boolean has_neighbor = tm.can_read();
 
     if( !has_label && !has_neighbor ){
diff --git a/developer/javacđź–‰/Ariadne_Node_Set.java b/developer/javacđź–‰/Ariadne_Node_Set.java
new file mode 100644 (file)
index 0000000..d5974f9
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+A node with a finite fixed set of neighbors.
+
+
+*/
+
+package com.ReasoningTechnology.Ariadne;
+
+import java.util.HashSet;
+import java.util.Arrays;
+
+// LT == Label Type
+public class Ariadne_Node_Set<LT extends Ariadne_Label> extends Ariadne_Node_FD<LT>{
+
+  // Owned by the class
+  //
+
+  @SafeVarargs
+  public static <T extends Ariadne_Label> Ariadne_Node_Set<T> make(T label ,T... neighbors){
+    return new Ariadne_Node_Set<>(label ,neighbors);
+  }
+
+  // Data owned by the instance
+  //
+
+  private final HashSet<LT> neighbor_set;
+
+  // Constructors
+  // 
+
+  @SafeVarargs
+  protected Ariadne_Node_Set(LT label ,LT... neighbors){
+    super( label );
+    this.neighbor_set = new HashSet<>();
+    if( neighbors != null ){
+      this.neighbor_set.addAll(Arrays.asList(neighbors));
+    }
+  }
+
+  // Instance interface
+  //
+  
+  @Override public Ariadne_TM_SR_NX_F<LT> neighbor(){
+    //    return Ariadne_TM_SR_NX_Set.make(neighbor_set);
+    return Ariadne_TM_SR_NX_Set.<LT>make(neighbor_set);
+  }
+
+  // Good citizen
+  //
+
+
+}
diff --git a/developer/javacđź–‰/Ariadne_TM_SR_ND_Depth.xjava b/developer/javacđź–‰/Ariadne_TM_SR_ND_Depth.xjava
new file mode 100644 (file)
index 0000000..f2ae716
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+Depth first traversal of a graph.
+
+Descent ends when reaching a cycle or a leaf node.
+
+*/
+package com.ReasoningTechnology.Ariadne;
+
+import java.util.HashSet;
+import java.util.ArrayList;
+import java.util.List;
+
+
+
+//    ,SiblingContext extends Ariadne_TM_SR_NX_Set< HashSet<Label> >
+class TM_SR_NX_Depth
+  <
+    Label extends Ariadne_Label
+    ,Node extends Ariadne_Node_FD<Label>
+    ,Graph extends Ariadne_Graph_FD<Label ,Node>
+    > 
+  extends Ariadne_TM_SR_NX_F<Ariadne_Label>
+{
+
+  // ----------------------------------------
+  // static
+  //
+  <
+    Label extends Ariadne_Label
+    ,Node extends Ariadne_Node_FD<Label>
+    ,Graph extends Ariadne_Graph_FD<Label ,Node>
+  >
+  TM_SR_NX_Depth<Label ,Node ,Graph>
+  make(Graph graph){
+    if(graph == null) return null;
+    if(graph.start() == null) return null;
+    TM_SR_NX_Depth depth = new TM_SR_NX_Depth(graph);
+    return depth;
+  }
+
+  // ----------------------------------------
+  // instance data
+  //
+
+  protected Graph graph;
+  protected Ariadne_ContextStack<SiblingContext ,Label> context_stack;
+  protected Ariadne_ContextStac
+    <
+      
+      SiblingContext
+        
+    > context_stack_tm;
+  protected Label cycle_node_label;
+
+  // ----------------------------------------
+  // constructor
+  //
+
+  protected TM_SR_NX_Depth(Graph graph){
+    graph = graph;
+    context_stack = Ariadne_ContextStack.make();
+    context_stack.push( graph.start() );
+    context_stack_tm = Ariadne_TM_SR_NX_Array.make(context_stack);
+    cycle_node_label = null;
+    extend_down();
+    set_topology(topo_segment);
+  }
+
+  // ----------------------------------------
+  // instance interface implementation
+  //
+
+  public enum BacktrackResult{
+    NO_CONTEXT
+    ,CYCLE
+    ,SUCCESS
+    ,DEPLETED
+  }
+  public BacktrackResult backtrack(){
+    if( isEmpty() ){
+      return BacktrackResult.NO_CONTEXT;
+    }
+
+    do{
+      pop();
+      if( isEmpty() ) return BacktrackResult.DEPLETED;
+      StepResult step_result = top_step();
+      switch( step_result ){
+        case NOT_CANSTEP:
+          continue;
+        case CYCLE:
+          return BacktrackResult.CYCLE;
+        case SUCCESS:
+          return BacktrackResult.SUCCESS;
+        default:
+          throw new UnsupportedOperationException(
+            "Ariadne_ContextStack::backtrack: Unknown result from top_step."
+            );
+      }
+    }while(true);
+  }
+
+  // Typically called after backtracking.
+  // The base node, that the function extends down from, will already be in the path.
+  // Returns true upon finding new read value, false upon finding a cycle.
+  public enum DescendResult{
+    NO_CONTEXT
+    ,LEAF
+    ,CYCLE
+  }
+  public DescendResult descend(){
+    if( isEmpty() ){
+      return DescendResult.NO_CONTEXT;
+    }
+
+    Label node_label = top().read();
+    Node node;
+
+    do{
+      node = graph.node(node_label);
+      if( node == null ){
+        throw new UnsupportedOperationException(
+          "Ariadne_ContextStack::descend: SiblingContext node label not found in the graph."
+          );
+      }
+
+      @SuppressWarnings("unchecked")
+      SiblingContext s = (SiblingContext)node.neighbor(); // this is a downward extension
+      PushResult result = push(s);
+      switch( result ){
+        case CYCLE:
+          return DescendResult.CYCLE;
+        case NO_CONTEXT:
+          return DescendResult.LEAF;
+        case SUCCESS:
+          node_label = s.read();
+          break; // from the switch statement
+        default:
+          throw new UnsupportedOperationException("Ariadne_ContextStack::descend result from push not known to descend.");
+      }
+    }while(true);
+  }
+
+
+  // being a good object citizen
+  //
+  protected class SegmentTopo implements TopoIface<RT>{
+    @Override public boolean can_read(){ return true; }
+    @Override public RT read(){ return (RT) read_value; }
+    @Override public boolean can_step(){ return true; }
+    @Override public void step(){
+      read_value = null;
+    }
+    @Override public Topology topology(){ return Topology.SEGMENT; }
+  }
+  protected final TopoIface<RT> topo_segment = new SegmentTopo();
+
+  protected class RightmostTopo implements TopoIface<RT>{
+    @Override public boolean can_read(){ return true; }
+    @Override public RT read(){ return read_value; }
+    @Override public boolean can_step(){ return false; }
+    @Override public void step(){
+      throw new UnsupportedOperationException("Cannot step from RIGHTMOST topo.");
+    }
+    @Override public Topology topology(){ return Topology.RIGHTMOST; }
+  }
+  protected final TopoIface<RT> topo_rightmost = new RightmostTopo();
+
+}
index ecd08a4..b8f1e2c 100644 (file)
@@ -3,7 +3,7 @@ package com.ReasoningTechnology.Ariadne;
 import java.util.Set;
 import java.util.Iterator;
 
-public class Ariadne_TM_SR_NX_Set<RT> extends Ariadne_TM_SR_NX<RT>{
+public class Ariadne_TM_SR_NX_Set<RT> extends Ariadne_TM_SR_NX_F<RT>{
 
   // Static methods
   public static <RT> Ariadne_TM_SR_NX_Set<RT> make(Set<RT> set){